Socket
Socket
Sign inDemoInstall

github.com/creachadair/jrpc2

Package Overview
Dependencies
7
Alerts
File Explorer

Install Socket

Detect and block malicious and high-risk dependencies

Install

    github.com/creachadair/jrpc2

Package jrpc2 implements a server and a client for the JSON-RPC 2.0 protocol defined by http://www.jsonrpc.org/specification. The *Server type implements a JSON-RPC server. A server communicates with a client over a channel.Channel, and dispatches client requests to user-defined method handlers. Method handlers are functions with this signature: A server finds the handler for a request by looking up its method name in a jrpc2.Assigner. A Handler decodes request parameters using the UnmarshalParams method on the Request: The handler package uses reflection to adapt functions that do not have this type to handlers. For example, given: call handler.New to convert Add to a handler function: The handler package also provides handler.Map, which implements the Assigner interface with a Go map. To advertise this function under the name "Add": Equipped with an Assigner we can now construct a Server: To start the server, we need a channel.Channel. Implementations of the Channel interface handle the framing, transmission, and receipt of JSON messages. The channel package implements some common framing disciplines for byte streams like pipes and sockets. For this example, we'll use a channel that communicates over stdin and stdout, with messages delimited by newlines: Now we can start the server: The Start method does not block. A server runs until its channel closes or it is stopped explicitly by calling srv.Stop(). To wait for the server to finish, call: This reports the error that led to the server exiting. The code for this example is available from tools/examples/adder/adder.go: Interact with the server by sending JSON-RPC requests on stdin, such as for example: The *Client type implements a JSON-RPC client. A client communicates with a server over a channel.Channel, and is safe for concurrent use by multiple goroutines. It supports batched requests and may have arbitrarily many pending requests in flight simultaneously. To create a client we need a channel: To send a single RPC, use the Call method: Call blocks until the response is received. Errors returned by the server have concrete type *jrpc2.Error. To issue a batch of concurrent requests, use the Batch method: Batch blocks until all the responses are received. An error from the Batch call reflects an error in sending the request: The caller must check each response separately for errors from the server. Responses are returned in the same order as the Spec values, save that notifications are omitted. To decode the result from a successful response, use its UnmarshalResult method: To close a client and discard all its pending work, call cli.Close(). A JSON-RPC notification is a one-way request: The client sends the request to the server, but the server does not reply. Use the Notify method of a client to send a notification: A notification is complete once it has been sent. Notifications can also be sent as part of a batch request: On the server, notifications are handled just like other requests, except that the return value is discarded once the handler returns. If a handler does not want to do anything for a notification, it can query the request: The example above shows a server with one method. A handler.Map works for any number of distinctly-named methods: Maps may be combined with the handler.ServiceMap type to export multiple services from the same server: This assigner dispatches "Math.Add" and "Math.Mul" to the arithmetic functions, and "Status.Get" to the getStatus function. A ServiceMap splits the method name on the first period ("."), and you may nest ServiceMaps more deeply if you require a more complex hierarchy. A Server issues concurrent requests to handlers in parallel, up to the limit given by the Concurrency field in ServerOptions. Two requests (either calls or notifications) are concurrent if they arrive as part of the same batch. In addition, two calls are concurrent if the time intervals between the arrival of the request objects and delivery of the response objects overlap. The server may issue concurrent requests to their handlers in any order. Non-concurrent requests are processed in order of arrival. Notifications, in particular, can only be concurrent with other requests in the same batch. This ensures a client that sends a notification can be sure its notification will be fully processed before any subsequent calls are issued to their handlers. These rules imply that the client cannot rely on the execution order of calls that overlap in time: If the caller needs to ensure that call A completes before call B starts, it must wait for A to return before invoking B. Per the JSON-RPC 2.0 spec, method names beginning with "rpc." are reserved by the implementation. By default, a server does not dispatch these methods to its assigner. In this configuration, the server exports a "rpc.serverInfo" method taking no parameters and returning a jrpc2.ServerInfo value. Setting the DisableBuiltin server option to true removes special treatment of "rpc." method names, and disables the rpc.serverInfo handler. When this option is true, method names beginning with "rpc." will be dispatched to the assigner like any other method. The AllowPush server option allows handlers to "push" requests back to the client. This is a non-standard extension of JSON-RPC used by some applications such as the Language Server Protocol (LSP). When this option is enabled, the server's Notify and Callback methods send requests back to the client. Otherwise, those methods will report an error: A method handler may use jrpc2.ServerFromContext to access the server from its context, and then invoke these methods on it. On the client side, the OnNotify and OnCallback options in jrpc2.ClientOptions provide hooks to which any server requests are delivered, if they are set. Since not all clients support server push, handlers should set a timeout when using the server Callback method; otherwise the callback may block forever for a client response that will never arrive. Both the Server and the Client use the standard context package to plumb cancellation and other request-specific metadata in handlers and calls. On the server, the context passed to a handler is automatically cancelled when the server shuts down or when the server's CancelRequest method is invoked for that request. In addition, the NewContext server option can be used to supply default timeouts or other context metadata. On the client, the context passed to the Call and CallResult methods governs the lifetime of the call. If the context ends before the call is complete, the client will terminate the call and report an error. Note that cancellation on the client is not automatically propagated to the server, as JSON-RPC does not define a standard mechanism to do so. One typical approach (used by LSP, for example) is to define a separate method on the server to handle cancellation requests. If an OnCancel hook is set in the ClientOptions, the client calls it when the context for a Call ends before the server has responded. This can be used to forward cancellation to the server separately.


Version published

Readme

Source

jrpc2

GoDoc

This repository provides a Go module that implements a JSON-RPC 2.0 client and server. There is also a working example in the Go playground.

Packages

  • Package jrpc2 implements the base client and server and standard error codes.

  • Package channel defines the communication channel abstraction used by the server & client.

  • Package handler defines support for adapting functions to service methods.

  • Package jhttp allows clients and servers to use HTTP as a transport.

  • Package server provides support for running a server to handle multiple connections, and an in-memory implementation for testing.

Versioning

From v1.0.0 onward, the API of this module is considered stable, and I intend to merge no breaking changes to the API without increasing the major version number. Following the conventions of semantic versioning, the minor version will be used to signify the presence of backward-compatible new features (for example, new methods, options, or types), while the patch version will be reserved for bug fixes, documentation updates, and other changes that do not modify the API surface.

Note, however, that this intent is limited to the package APIs as seen by the Go compiler: Changes to the implementation that change observable behaviour in ways not promised by the documentation, e.g., changing performance characteristics or the order of internal operations, are not protected. Breakage that results from reliance on undocumented side-effects of the current implementation are the caller's responsibility.

Implementation Notes

The following describes some of the implementation choices made by this module.

Batch requests and error reporting

The JSON-RPC 2.0 spec is ambiguous about the semantics of batch requests. Specifically, the definition of notifications says:

A Notification is a Request object without an "id" member. ... The Server MUST NOT reply to a Notification, including those that are within a batch request.

Notifications are not confirmable by definition, since they do not have a Response object to be returned. As such, the Client would not be aware of any errors (like e.g. "Invalid params", "Internal error").

This conflicts with the definition of batch requests, which asserts:

A Response object SHOULD exist for each Request object, except that there SHOULD NOT be any Response objects for notifications. ... The Response objects being returned from a batch call MAY be returned in any order within the Array. ... If the batch rpc call itself fails to be recognized as an valid JSON or as an Array with at least one value, the response from the Server MUST be a single Response object.

and includes examples that contain request values with no ID (which are, perforce, notifications) and report errors back to the client. Since order may not be relied upon, and there are no IDs, the client cannot correctly match such responses back to their originating requests.

This implementation resolves the conflict in favour of the batch rules. Specifically:

  • If a batch is empty or not valid JSON, the server reports error -32700 (Invalid JSON) as a single error Response object.

  • Otherwise, parse or validation errors resulting from any batch member without an ID are mapped to error objects with a null ID, in the same position in the reply as the corresponding request. Preservation of order is not required by the specification, but it ensures the server has stable behaviour.

Because a server is allowed to reorder the results, a client should not depend on this implementation detail.

FAQs

Last updated on 16 Nov 2023

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc