jsonrpc

package
v0.1.20 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 29, 2026 License: BSD-3-Clause, MIT Imports: 0 Imported by: 0

Documentation

Overview

Package jsonrpc2 is a minimal implementation of the JSON RPC 2 spec. https://www.jsonrpc.org/specification It is intended to be compatible with other implementations at the wire level.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrIdleTimeout is returned when serving timed out waiting for new connections.
	ErrIdleTimeout = errors.New("timed out waiting for new connections")

	// ErrNotHandled is returned from a Handler or Preempter to indicate it did
	// not handle the request.
	//
	// If a Handler returns ErrNotHandled, the server replies with
	// ErrMethodNotFound.
	ErrNotHandled = errors.New("JSON RPC not handled")

	// ErrAsyncResponse is returned from a handler to indicate it will generate a
	// response asynchronously.
	//
	// ErrAsyncResponse must not be returned for notifications,
	// which do not receive responses.
	ErrAsyncResponse = errors.New("JSON RPC asynchronous response")
)
View Source
var (
	// ErrParse is used when invalid JSON was received by the server.
	ErrParse = NewError(-32700, "JSON RPC parse error")
	// ErrInvalidRequest is used when the JSON sent is not a valid Request object.
	ErrInvalidRequest = NewError(-32600, "JSON RPC invalid request")
	// ErrMethodNotFound should be returned by the handler when the method does
	// not exist / is not available.
	ErrMethodNotFound = NewError(-32601, "JSON RPC method not found")
	// ErrInvalidParams should be returned by the handler when method
	// parameter(s) were invalid.
	ErrInvalidParams = NewError(-32602, "JSON RPC invalid params")
	// ErrInternal indicates a failure to process a call correctly
	ErrInternal = NewError(-32603, "JSON RPC internal error")

	// ErrServerOverloaded is returned when a message was refused due to a
	// server being temporarily unable to accept any new messages.
	ErrServerOverloaded = NewError(-32000, "JSON RPC overloaded")
	// ErrUnknown should be used for all non coded errors.
	ErrUnknown = NewError(-32001, "JSON RPC unknown error")
	// ErrServerClosing is returned for calls that arrive while the server is closing.
	ErrServerClosing = NewError(-32002, "JSON RPC server is closing")
	// ErrClientClosing is a dummy error returned for calls initiated while the client is closing.
	ErrClientClosing = NewError(-32003, "JSON RPC client is closing")
)

Functions

func EncodeIndent

func EncodeIndent(msg Message, prefix, indent string) ([]byte, error)

EncodeIndent is like EncodeMessage, but honors indents. TODO(rfindley): refactor so that this concern is handled independently. Perhaps we should pass in a json.Encoder?

func EncodeMessage

func EncodeMessage(msg Message) ([]byte, error)

Types

type Framer

type Framer interface {
	// Reader wraps a byte reader into a message reader.
	Reader(io.Reader) Reader
	// Writer wraps a byte writer into a message writer.
	Writer(io.Writer) Writer
}

Framer wraps low level byte readers and writers into jsonrpc2 message readers and writers. It is responsible for the framing and encoding of messages into wire form.

TODO(rfindley): rethink the framer interface, as with JSONRPC2 batching there is a need for Reader and Writer to be correlated, and while the implementation of framing here allows that, it is not made explicit by the interface.

Perhaps a better interface would be

Frame(io.ReadWriteCloser) (Reader, Writer).

func HeaderFramer

func HeaderFramer() Framer

HeaderFramer returns a new Framer. The messages are sent with HTTP content length and MIME type headers. This is the format used by LSP and others.

func RawFramer

func RawFramer() Framer

RawFramer returns a new Framer. The messages are sent with no wrapping, and rely on json decode consistency to determine message boundaries.

type Handler

type Handler interface {
	// Handle is invoked sequentially for each incoming request that has not
	// already been handled by a Preempter.
	//
	// If the Request has a nil ID, Handle must return a nil result,
	// and any error may be logged but will not be reported to the caller.
	//
	// If the Request has a non-nil ID, Handle must return either a
	// non-nil, JSON-marshalable result, or a non-nil error.
	//
	// The Context passed to Handle will be canceled if the
	// connection is broken or the request is canceled or completed.
	// (If Handle returns ErrAsyncResponse, ctx will remain uncanceled
	// until either Cancel or Respond is called for the request's ID.)
	Handle(ctx context.Context, req *Request) (result any, err error)
}

Handler handles messages on a connection.

type HandlerFunc

type HandlerFunc func(ctx context.Context, req *Request) (any, error)

A HandlerFunc implements the Handler interface for a standalone Handle function.

func (HandlerFunc) Handle

func (f HandlerFunc) Handle(ctx context.Context, req *Request) (any, error)

type ID

type ID struct {
	// contains filtered or unexported fields
}

ID is a Request identifier, which is defined by the spec to be a string, integer, or null. https://www.jsonrpc.org/specification#request_object

func Int64ID

func Int64ID(i int64) ID

Int64ID creates a new integer request identifier.

func MakeID

func MakeID(v any) (ID, error)

MakeID coerces the given Go value to an ID. The value is assumed to be the default JSON marshaling of a Request identifier -- nil, float64, or string.

Returns an error if the value type was a valid Request ID type.

TODO: ID can't be a json.Marshaler/Unmarshaler, because we want to omitzero. Simplify this package by making ID json serializable once we can rely on omitzero.

func StringID

func StringID(s string) ID

StringID creates a new string request identifier.

func (ID) IsValid

func (id ID) IsValid() bool

IsValid returns true if the ID is a valid identifier. The default value for ID will return false.

func (ID) Raw

func (id ID) Raw() any

Raw returns the underlying value of the ID.

type Message

type Message interface {
	// contains filtered or unexported methods
}

Message is the interface to all jsonrpc2 message types. They share no common functionality, but are a closed set of concrete types that are allowed to implement this interface. The message types are *Request and *Response.

func DecodeMessage

func DecodeMessage(data []byte) (Message, error)

type Preempter

type Preempter interface {
	// Preempt is invoked for each incoming request before it is queued for handling.
	//
	// If Preempt returns ErrNotHandled, the request will be queued,
	// and eventually passed to a Handle call.
	//
	// Otherwise, the result and error are processed as if returned by Handle.
	//
	// Preempt must not block. (The Context passed to it is for Values only.)
	Preempt(ctx context.Context, req *Request) (result any, err error)
}

Preempter handles messages on a connection before they are queued to the main handler. Primarily this is used for cancel handlers or notifications for which out of order processing is not an issue.

type PreempterFunc

type PreempterFunc func(ctx context.Context, req *Request) (any, error)

A PreempterFunc implements the Preempter interface for a standalone Preempt function.

func (PreempterFunc) Preempt

func (f PreempterFunc) Preempt(ctx context.Context, req *Request) (any, error)

type Reader

type Reader interface {
	// Read gets the next message from the stream.
	Read(context.Context) (Message, error)
}

Reader abstracts the transport mechanics from the JSON RPC protocol. A Conn reads messages from the reader it was provided on construction, and assumes that each call to Read fully transfers a single message, or returns an error. A reader is not safe for concurrent use, it is expected it will be used by a single Conn in a safe manner.

type Request

type Request struct {
	// ID of this request, used to tie the Response back to the request.
	// This will be nil for notifications.
	ID ID
	// Method is a string containing the method name to invoke.
	Method string
	// Params is either a struct or an array with the parameters of the method.
	Params json.RawMessage
}

Request is a Message sent to a peer to request behavior. If it has an ID it is a call, otherwise it is a notification.

func NewCall

func NewCall(id ID, method string, params any) (*Request, error)

NewCall constructs a new Call message for the supplied ID, method and parameters.

func NewNotification

func NewNotification(method string, params any) (*Request, error)

NewNotification constructs a new Notification message for the supplied method and parameters.

func (*Request) IsCall

func (msg *Request) IsCall() bool

type Response

type Response struct {
	// result is the content of the response.
	Result json.RawMessage
	// err is set only if the call failed.
	Error error
	// id of the request this is a response to.
	ID ID
}

Response is a Message used as a reply to a call Request. It will have the same ID as the call it is a response to.

func NewResponse

func NewResponse(id ID, result any, rerr error) (*Response, error)

NewResponse constructs a new Response message that is a reply to the supplied. If err is set result may be ignored.

type WireError

type WireError struct {
	// Code is an error code indicating the type of failure.
	Code int64 `json:"code"`
	// Message is a short description of the error.
	Message string `json:"message"`
	// Data is optional structured data containing additional information about the error.
	Data json.RawMessage `json:"data,omitempty"`
}

WireError represents a structured error in a Response.

func NewError

func NewError(code int64, message string) *WireError

NewError returns an error that will encode on the wire correctly. The standard codes are made available from this package, this function should only be used to build errors for application specific codes as allowed by the specification.

func (*WireError) Error

func (err *WireError) Error() string

func (*WireError) Is

func (err *WireError) Is(other error) bool

type Writer

type Writer interface {
	// Write sends a message to the stream.
	Write(context.Context, Message) error
}

Writer abstracts the transport mechanics from the JSON RPC protocol. A Conn writes messages using the writer it was provided on construction, and assumes that each call to Write fully transfers a single message, or returns an error. A writer is not safe for concurrent use, it is expected it will be used by a single Conn in a safe manner.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL