p-hatan/ mirror

pub repository

mirror.p-hatan.com

json_rpc_2

4.1.0

Utilities to write a client or server using the JSON-RPC 2.0 spec.

Download archive

Readme

Build Status pub package package publisher

A library that implements the JSON-RPC 2.0 spec.

Server

A JSON-RPC 2.0 server exposes a set of methods that can be called by clients. These methods can be registered using Server.registerMethod:

import 'dart:io';

import 'package:json_rpc_2/json_rpc_2.dart';
import 'package:web_socket_channel/io.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

void main() async {
  var httpServer = await HttpServer.bind(InternetAddress.loopbackIPv4, 4321);
  var connectedChannels =
      httpServer.transform(WebSocketTransformer()).map(IOWebSocketChannel.new);
  connectedChannels.listen(handleClient);
}

void handleClient(WebSocketChannel socket) {
  // The socket is a `StreamChannel<dynamic>` because it might emit binary
  // `List<int>`, but JSON RPC 2 only works with Strings so we assert it only
  // emits those by casting it.
  var server = Server(socket.cast<String>());

  // Any string may be used as a method name. JSON-RPC 2.0 methods are
  // case-sensitive.
  var i = 0;
  server.registerMethod('count', () {
    // Just return the value to be sent as a response to the client. This can
    // be anything JSON-serializable, or a Future that completes to something
    // JSON-serializable.
    return i++;
  });

  // Methods can take parameters. They're presented as a `Parameters` object
  // which makes it easy to validate that the expected parameters exist.
  server.registerMethod('echo', (Parameters params) {
    // If the request doesn't have a "message" parameter this will
    // automatically send a response notifying the client that the request
    // was invalid.
    return params['message'].value;
  });

  // `Parameters` has methods for verifying argument types.
  server.registerMethod('subtract', (Parameters params) {
    // If "minuend" or "subtrahend" aren't numbers, this will reject the
    // request.
    return params['minuend'].asNum - params['subtrahend'].asNum;
  });

  // [Parameters] also supports optional arguments.
  server.registerMethod('sort', (Parameters params) {
    var list = params['list'].asList;
    list.sort();
    if (params['descendint'].asBoolOr(false)) {
      return list.reversed;
    } else {
      return list;
    }
  });

  // A method can send an error response by throwing a `RpcException`.
  // Any positive number may be used as an application- defined error code.
  const dividByZero = 1;
  server.registerMethod('divide', (Parameters params) {
    var divisor = params['divisor'].asNum;
    if (divisor == 0) {
      throw RpcException(dividByZero, 'Cannot divide by zero.');
    }

    return params['dividend'].asNum / divisor;
  });

  // To give you time to register all your methods, the server won't start
  // listening for requests until you call `listen`. Messages are buffered until
  // listen is called. The returned Future won't complete until the connection
  // is closed.
  server.listen();
}

Client

A JSON-RPC 2.0 client calls methods on a server and handles the server's responses to those method calls. These methods can be called using Client.sendRequest:

import 'package:json_rpc_2/json_rpc_2.dart';
import 'package:pedantic/pedantic.dart';
import 'package:web_socket_channel/web_socket_channel.dart';

void main() async {
  var socket = WebSocketChannel.connect(Uri.parse('ws://localhost:4321'));
  var client = Client(socket.cast<String>());

  // The client won't subscribe to the input stream until you call `listen`.
  // The returned Future won't complete until the connection is closed.
  unawaited(client.listen());

  // This calls the "count" method on the server. A Future is returned that
  // will complete to the value contained in the server's response.
  var count = await client.sendRequest('count');
  print('Count is $count');

  // Parameters are passed as a simple Map or, for positional parameters, an
  // Iterable. Make sure they're JSON-serializable!
  var echo = await client.sendRequest('echo', {'message': 'hello'});
  print('Echo says "$echo"!');

  // A notification is a way to call a method that tells the server that no
  // result is expected. Its return type is `void`; even if it causes an
  // error, you won't hear back.
  client.sendNotification('count');

  // If the server sends an error response, the returned Future will complete
  // with an RpcException. You can catch this error and inspect its error
  // code, message, and any data that the server sent along with it.
  try {
    await client.sendRequest('divide', {'dividend': 2, 'divisor': 0});
  } on RpcException catch (error) {
    print('RPC error ${error.code}: ${error.message}');
  }

  await client.close();
}

Peer

Although JSON-RPC 2.0 only explicitly describes clients and servers, it also mentions that two-way communication can be supported by making each endpoint both a client and a server. This package supports this directly using the Peer class, which implements both Client and Server. It supports the same methods as those classes, and automatically makes sure that every message from the other endpoint is routed and handled correctly.

Publishing automation

For information about our publishing automation and release process, see https://github.com/dart-lang/ecosystem/wiki/Publishing-automation.

Changelog

4.1.0

  • Forward errors within Peer when it is acting as a client.

4.0.0

  • Add custom ID generator option to clients, which allows for String ids.
  • Breaking: When String ids are present in a response, we no longer automatically try to parse them as integers. This behavior was never a part of the spec, and is not compatible with allowing custom ID generators.

3.0.3

  • Require Dart 3.4
  • Move to dart-lang/tools monorepo.

3.0.2

  • Switch to using package:lints.
  • Address a few analysis hint violations.
  • Populate the pubspec repository field.

3.0.1

  • Fix a bug where a null result to a request caused an exception.

3.0.0

  • Migrate to null safety.
  • Accept responses even if the server converts the ID to a String.

2.2.2

  • Fix Peer.close() throwing Bad state: Future already completed.

2.2.1

  • Fix Peer requests not terminating when the underlying channel is closed.

2.2.0

  • Added strictProtocolChecks named parameter to Server and Peer constructors. Setting this parameter to false will result in the server not rejecting requests missing the jsonrpc parameter.

2.1.1

  • Fixed issue where throwing RpcException.methodNotFound in an asynchronous fallback handler would not result in the next fallback being executed.
  • Updated minimum SDK to Dart 2.2.0.

2.1.0

  • Server and related classes can now take an onUnhandledError callback to notify callers of unhandled exceptions.

2.0.10

  • Allow stream_channel version 2.x

2.0.8

  • Updated SDK version to 2.0.0-dev.17.0

2.0.7

  • When a Client is closed before a request completes, the error sent to that request's Future now includes the request method to aid in debugging.

2.0.6

  • Internal changes only.

2.0.5

  • Internal changes only.

2.0.4

  • Client.sendRequest() now throws a StateError if the client is closed while the request is in-flight. This avoids dangling Futures that will never be completed.

  • Both Client.sendRequest() and Client.sendNotification() now throw StateErrors if they're called after the client is closed.

2.0.3

  • Fix new strong-mode warnings.

2.0.2

  • Fix all strong-mode warnings.

2.0.1

  • Fix a race condition in which a StateError could be top-leveled if Peer.close() was called before the underlying channel closed.

2.0.0

  • Breaking change: all constructors now take a StreamChannel rather than a Stream/StreamSink pair.

  • Client.sendRequest() and Client.sendNotification() no longer throw StateErrors after the connection has been closed but before Client.close() has been called.

  • The various close() methods may now be called before their corresponding listen() methods.

  • The various close() methods now wait on the result of closing the underlying StreamSink. Be aware that in some circumstances StreamControllers' Sink.close() futures may never complete.

1.2.0

  • Add Client.isClosed and Server.isClosed, which make it possible to synchronously determine whether the connection is open. In particular, this makes it possible to reliably tell whether it's safe to call Client.sendRequest.

  • Fix a race condition in Server where a StateError could be thrown if the connection was closed in the middle of handling a request.

  • Improve stack traces for error responses.

1.1.1

  • Update the README to match the current API.

1.1.0

  • Add a done getter to Client, Server, and Peer.

1.0.0

  • Add a Client class for communicating with external JSON-RPC 2.0 servers.

  • Add a Peer class that's both a Client and a Server.

0.1.0

  • Remove Server.handleRequest() and Server.parseRequest(). Instead, new Server() takes a Stream and a StreamSink and uses those behind-the-scenes for its communication.

  • Add Server.listen(), which causes the server to begin listening to the underlying request stream.

  • Add Server.close(), which closes the underlying request stream and response sink.

0.0.2+3

  • Widen the version constraint for stack_trace.

0.0.2+2

  • Fix error response to include data from RpcException when not a map.

Installing

export PUB_HOSTED_URL=https://pub.mirror.p-hatan.com
flutter pub add json_rpc_2
pubspec.yaml
name: json_rpc_2
version: 4.1.0
description: >-
  Utilities to write a client or server using the JSON-RPC 2.0 spec.
repository: https://github.com/dart-lang/tools/tree/main/pkgs/json_rpc_2
issue_tracker: https://github.com/dart-lang/tools/issues?q=is%3Aissue+is%3Aopen+label%3Apackage%3Ajson_rpc_2

environment:
  sdk: ^3.4.0

dependencies:
  stack_trace: ^1.10.0
  stream_channel: ^2.1.0

dev_dependencies:
  dart_flutter_team_lints: ^3.0.0
  test: ^1.25.5
  web_socket_channel: ^3.0.0

Version history

VersionPublishedArchiveSHA-256
0.0.12014-03-21T19:46:16.100640ZDownload09545ad68fe039097a917f493a092da70d3de56e9c1895bb17b4f63be3d5a81d
0.0.22014-03-25T00:04:29.024110ZDownload39443523e57e6c3ce727bfac0512fc14d4b73b5b16a09ef995953265716367ee
0.0.2+12014-04-03T21:32:22.272630ZDownloadb7c26537523d9800da9382b4aaeff362c63023f66c21da3830acc7829f3fffa3
0.0.2+22014-04-04T22:16:18.194490ZDownloaddd679bcd0ce54d8b71b178d7c2563572f69a0f57ff39e4908ace69e0519be83e
0.0.2+32014-06-02T18:41:20.507230ZDownloadf1af76e5bf29f16ffdf334d82cf9f81f175ff472c513a707590b9380a75631ed
0.1.02014-06-04T20:43:34.047660ZDownloadb398b9de5af47ccc4ef80d9f21397d0a14a184800c26f062e034f3c812047717
1.0.02014-11-11T23:11:13.321240ZDownload63445e9aff16c9c342149acb9ced352ae24bf76f91d490b8e94d6dd7eab8a817
1.1.02015-01-21T02:41:51.462830ZDownload2254530f41c902a0f667e6cee3e0551ac47ce319a34ce2a489272907c5f242ae
1.1.12015-02-06T00:27:38.066250ZDownload2767999dd1e50ca73c8d900688f548f492968cb7200adb7ff2b618e39703c520
1.2.02015-09-15T00:32:49.653ZDownloadaea6d5a61420b01c5dc167f03c7f5330fefa6cd327553fd90aa9a15a7c9e2356
2.0.02016-02-02T20:22:28.476ZDownloadb9b376bda0a382ba8c4c6f5b3b10d58307f75c1fb5d7ec58176144a5cb5b7a12
2.0.12016-04-14T22:19:15.210ZDownload75bb8a7cbf939d62e28d26435ec041f0c4ea4eb8b184831ffcd78a5c85809d24
2.0.22016-08-09T21:51:35.659ZDownload7f61013100b9e3f445dea5d98532c37b68aaa6ad09d7e2d2853f3c10f6f5b37c
2.0.32016-11-01T21:36:07.139ZDownloadf1ba4f93f12c5f86d85191031ae03bfbdb4b920a0cc25b2a4e5226b7221e9f84
2.0.42017-02-15T19:43:16.178ZDownloadcd9f5ebce5ac3da2914cce51c2a25a682a86122a1ad1fd0213198889101c3935
2.0.52018-01-06T00:36:45.436557ZDownloada5b25a752411ab344161d1db2e6cf0fa8a070b804d01876ad03e0853eb188048
2.0.62018-01-11T18:51:53.414198ZDownload63ba979e888bffa5ded762bfe74a5750677617a688c3a360b1d21d98f73fc750
2.0.72018-01-17T20:54:12.228895ZDownloadc0e2657eb89e6d7979cdd4ffb8ba775ae1768df37f05ad447563ca96cdc41bd1
2.0.82018-05-25T15:49:26.869240ZDownloada0fff6620c1d73025f122e4696394e37d61e23a204b0c5904f48f4dce163e27e
2.0.92018-07-20T21:57:53.227378ZDownloadf6dba580b18dca16e3263973298df774783364966d67b963c72c4b7837115c26
2.0.102019-03-27T21:59:59.094214ZDownloadddc01403be10a13fd1a75aae3fcb0cd130ab9e48afd6879ce522c5ced7ccbf53
2.1.02019-04-23T17:35:57.438333ZDownload282d980a3d033f80d5184c23c4941df32bcc301e78015ae51cd21fbe14e8f799
2.1.12020-04-21T20:33:19.738281ZDownload89bc583bcf2b13b446f08364c06754a7fb54c5b2bc1ed430e02547933088275c
2.2.02020-05-20T23:05:16.431439ZDownload36bf81f9fc72e47c36a3df1b9d6ebea86218d38b69958390861c51524b0423c7
2.2.12020-06-08T23:57:39.441024ZDownload2048a29ef2e8fa15a4856d64d926bda19480305b076defe44c611993a1a10221
2.2.22020-08-28T23:34:33.367643ZDownload37c35bfeb12393cced89746f2bf55699fc6e87c16572ce5e4a0733cee87c3c9f
3.0.02021-04-28T15:51:45.759257ZDownload97e555e622ff5e3c32020af9fd9370636a464739cf8ac81f664687eb4334269e
3.0.12021-05-06T20:42:48.550100ZDownloadf03482ca7adb5f3a5f0854d90005e2523f93aa6f510741aabe2f026fb5a65ae8
3.0.22022-06-15T21:50:23.997326ZDownload5e469bffa23899edacb7b22787780068d650b106a21c76db3c49218ab7ca447e
3.0.32024-10-28T08:34:42.154918ZDownload246b321532f0e8e2ba474b4d757eaa558ae4fdd0688fdbc1e1ca9705f9b8ca0e
4.0.02025-05-01T19:32:39.449767ZDownload3c46c2633aec07810c3d6a2eb08d575b5b4072980db08f1344e66aeb53d6e4a7
4.1.02026-02-18T00:50:42.589361ZDownload82dfd37d3b2e5030ae4729e1d7f5538cbc45eb1c73d618b9272931facac3bec1

Dependencies

stack_trace "^1.10.0"

stream_channel "^2.1.0"