Documentation
¶
Overview ¶
Package http provides HTTP transport implementation for JSON-RPC communication.
Example Usage:
Server:
handlers := map[string]Handler{
"greet": func(ctx context.Context, req *jsonrpc.Request) *jsonrpc.Response {
var params map[string]any
if err := json.Unmarshal(req.Params, ¶ms); err != nil {
return NewErrorResponse(jsonrpc.InvalidParams, "Invalid params", nil, req.ID)
}
name := params["name"].(string)
return NewResponse("Hello "+name, req.ID)
},
}
server := NewHttpServer("127.0.0.1:8080", "/rpc", handlers)
log.Println("Server starting on :8080/rpc")
if err := server.ListenAndServe(); err != nil {
log.Fatal(err)
}
Client:
client := NewHttpClient(&http.Client{})
if err := client.Connect(context.Background(), "http://127.0.0.1:8080/rpc"); err != nil {
log.Fatal(err)
}
defer client.Close()
req := &Request{
JSONRPC: "2.0",
Method: "greet",
Params: map[string]any{"name": "World"},
ID: 1,
}
if err := client.WriteRequest(context.Background(), req); err != nil {
log.Fatal(err)
}
resp, err := client.ReadResponse(context.Background())
if err != nil {
log.Fatal(err)
}
fmt.Printf("Response: %v\n", resp.Result)
Alternative: Using the high-level Client interface:
client := NewClient(NewHttpCodec(&http.Client{}))
client.Connect(context.Background(), "http://127.0.0.1:8080/rpc")
defer client.Close()
var result string
err := client.CallWithResult(context.Background(), "greet", map[string]any{"name": "World"}, &result)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Result: %s\n", result)
Package tcp provides TCP transport implementation for JSON-RPC communication.
Example Usage:
Server:
server, err := NewTcpServer("127.0.0.1:8080")
if err != nil {
log.Fatal(err)
}
defer server.Close()
for {
codec, err := server.Accept(context.Background())
if err != nil {
log.Printf("Accept error: %v", err)
continue
}
go func() {
defer codec.Close()
for {
req, err := codec.ReadRequest(context.Background())
if err != nil {
log.Printf("Read error: %v", err)
return
}
// Process request and create response
var params map[string]any
if err := json.Unmarshal(req.Params, ¶ms); err != nil {
// Handle error
continue
}
resp := &Response{
JSONRPC: "2.0",
Result: json.RawMessage(`"Hello ` + params["name"].(string) + `"`),
ID: req.ID,
}
if err := codec.WriteResponse(context.Background(), resp); err != nil {
log.Printf("Write error: %v", err)
return
}
}
}()
}
Client:
client := NewTcpClient()
if err := client.Connect(context.Background(), "127.0.0.1:8080"); err != nil {
log.Fatal(err)
}
defer client.Close()
req := &Request{
JSONRPC: "2.0",
Method: "greet",
Params: map[string]any{"name": "World"},
ID: 1,
}
if err := client.WriteRequest(context.Background(), req); err != nil {
log.Fatal(err)
}
resp, err := client.ReadResponse(context.Background())
if err != nil {
log.Fatal(err)
}
fmt.Printf("Response: %v\n", resp.Result)
Package udp provides UDP transport implementation for JSON-RPC communication.
Example Usage:
Server:
server, err := NewUdpServer("127.0.0.1:8080")
if err != nil {
log.Fatal(err)
}
defer server.Close()
for {
codec, err := server.Accept(context.Background())
if err != nil {
log.Printf("Accept error: %v", err)
continue
}
go func() {
defer codec.Close()
req, err := codec.ReadRequest(context.Background())
if err != nil {
log.Printf("Read error: %v", err)
return
}
// Process request and create response
var params map[string]any
if err := json.Unmarshal(req.Params, ¶ms); err != nil {
// Handle error
return
}
resp := &Response{
JSONRPC: "2.0",
Result: json.RawMessage(`"Hello ` + params["name"].(string) + `"`),
ID: req.ID,
}
if err := codec.WriteResponse(context.Background(), resp); err != nil {
log.Printf("Write error: %v", err)
}
}()
}
Client:
client := NewUdpClient()
if err := client.Connect(context.Background(), "127.0.0.1:8080"); err != nil {
log.Fatal(err)
}
defer client.Close()
req := &Request{
JSONRPC: "2.0",
Method: "greet",
Params: map[string]any{"name": "World"},
ID: 1,
}
if err := client.WriteRequest(context.Background(), req); err != nil {
log.Fatal(err)
}
resp, err := client.ReadResponse(context.Background())
if err != nil {
log.Fatal(err)
}
fmt.Printf("Response: %v\n", resp.Result)
Index ¶
- Constants
- Variables
- type BatchCall
- type BatchResponse
- type BufferedUdpCodec
- type Client
- func (c *Client) BatchCall(ctx context.Context, calls []BatchCall) ([]BatchResponse, error)
- func (c *Client) Call(ctx context.Context, method string, params any) (*Response, error)
- func (c *Client) CallWithResult(ctx context.Context, method string, params any, result any) error
- func (c *Client) Close() error
- func (c *Client) Connect(ctx context.Context, address string) error
- func (c *Client) IsConnected() bool
- func (c *Client) Notify(ctx context.Context, method string, params any) error
- type ClientCodec
- type Codec
- type Error
- type Handler
- type HttpClient
- type HttpCodec
- func (c *HttpCodec) Close() error
- func (c *HttpCodec) ReadRequest(ctx context.Context) (*Request, error)
- func (c *HttpCodec) ReadResponse(ctx context.Context) (*Response, error)
- func (c *HttpCodec) RemoteAddr() string
- func (c *HttpCodec) WriteRequest(ctx context.Context, req *Request) error
- func (c *HttpCodec) WriteResponse(ctx context.Context, resp *Response) error
- type HttpServer
- func (c *HttpServer) Accept(ctx context.Context) (Codec, error)
- func (c *HttpServer) Close() error
- func (c *HttpServer) ListenAndServe() error
- func (c *HttpServer) ListenAndServeContext(ctx context.Context) error
- func (c *HttpServer) ReadRequest(ctx context.Context) (any, error)
- func (c *HttpServer) ReadResponse(ctx context.Context) (any, error)
- func (c *HttpServer) RemoteAddr() string
- func (c *HttpServer) WriteRequest(ctx context.Context, req any) error
- func (c *HttpServer) WriteResponse(ctx context.Context, resp any) error
- type Request
- type Response
- type ServerCodec
- type TcpClient
- type TcpCodec
- func (c *TcpCodec) Close() error
- func (c *TcpCodec) ReadRequest(ctx context.Context) (*Request, error)
- func (c *TcpCodec) ReadResponse(ctx context.Context) (*Response, error)
- func (c *TcpCodec) RemoteAddr() string
- func (c *TcpCodec) WriteRequest(ctx context.Context, req *Request) error
- func (c *TcpCodec) WriteResponse(ctx context.Context, resp *Response) error
- type TcpServer
- func (s *TcpServer) Accept(ctx context.Context) (Codec, error)
- func (s *TcpServer) Close() error
- func (s *TcpServer) ReadRequest(ctx context.Context) (*Request, error)
- func (s *TcpServer) ReadResponse(ctx context.Context) (*Response, error)
- func (s *TcpServer) RemoteAddr() string
- func (s *TcpServer) WriteRequest(ctx context.Context, req *Request) error
- func (s *TcpServer) WriteResponse(ctx context.Context, resp *Response) error
- type UdpClient
- type UdpCodec
- func (c *UdpCodec) Close() error
- func (c *UdpCodec) LocalAddr() string
- func (c *UdpCodec) ReadRequest(ctx context.Context) (*Request, error)
- func (c *UdpCodec) ReadResponse(ctx context.Context) (*Response, error)
- func (c *UdpCodec) RemoteAddr() string
- func (c *UdpCodec) SetTimeout(timeout time.Duration)
- func (c *UdpCodec) WriteRequest(ctx context.Context, req *Request) error
- func (c *UdpCodec) WriteResponse(ctx context.Context, resp *Response) error
- type UdpServer
- func (s *UdpServer) Accept(ctx context.Context) (Codec, error)
- func (s *UdpServer) Close() error
- func (s *UdpServer) ReadRequest(ctx context.Context) (*Request, error)
- func (s *UdpServer) ReadResponse(ctx context.Context) (*Response, error)
- func (s *UdpServer) RemoteAddr() string
- func (s *UdpServer) SetTimeout(timeout time.Duration)
- func (s *UdpServer) WriteRequest(ctx context.Context, req *Request) error
- func (s *UdpServer) WriteResponse(ctx context.Context, resp *Response) error
Constants ¶
const ( // MaxUDPPacketSize is the maximum size for UDP packets (safe size for most networks) MaxUDPPacketSize = 1400 // DefaultTimeout is the default timeout for UDP operations DefaultTimeout = 30 * time.Second )
const ( ParseError = -32700 InvalidRequest = -32600 MethodNotFound = -32601 InvalidParams = -32602 InternalError = -32603 )
Standard error codes as defined in JSON-RPC 2.0 specification
const Version = "2.0"
Version represents the JSON-RPC version string
Variables ¶
var ( // ErrHttpClientNotAvailable indicates the HTTP client is not available ErrHttpClientNotAvailable = errors.New("http: client not available") // ErrHttpResponseWriterNotAvailable indicates the HTTP response writer is not available ErrHttpResponseWriterNotAvailable = errors.New("http: response writer not available") // ErrHttpRequestNotAvailable indicates the HTTP request is not available ErrHttpRequestNotAvailable = errors.New("http: request not available") // ErrHttpNotSupported indicates an operation is not supported ErrHttpNotSupported = errors.New("http: operation not supported") )
var ( // ErrTcpConnectionClosed indicates the connection has been closed ErrTcpConnectionClosed = errors.New("tcp: connection closed") // ErrTcpInvalidLengthPrefix indicates an invalid length prefix in the message ErrTcpInvalidLengthPrefix = errors.New("tcp: invalid length prefix") // ErrTcpNotSupported indicates an operation is not supported ErrTcpNotSupported = errors.New("tcp: operation not supported") )
var ( // ErrUdpConnectionClosed indicates the connection has been closed ErrUdpConnectionClosed = errors.New("udp: connection closed") // ErrUdpNotSupported indicates an operation is not supported ErrUdpNotSupported = errors.New("udp: operation not supported") // ErrUdpMessageTooLarge indicates the message exceeds UDP packet size limits ErrUdpMessageTooLarge = errors.New("udp: message too large for UDP packet") // ErrUdpTimeout indicates a timeout occurred ErrUdpTimeout = errors.New("udp: operation timed out") )
Functions ¶
This section is empty.
Types ¶
type BatchResponse ¶
BatchResponse represents a response in a batch
type BufferedUdpCodec ¶
type BufferedUdpCodec struct {
*UdpCodec
// contains filtered or unexported fields
}
BufferedUdpCodec wraps UdpCodec to handle the first message received during Accept
func (*BufferedUdpCodec) ReadRequest ¶
func (c *BufferedUdpCodec) ReadRequest(ctx context.Context) (*Request, error)
ReadRequest reads the buffered request first, then normal requests
func (*BufferedUdpCodec) ReadResponse ¶
func (c *BufferedUdpCodec) ReadResponse(ctx context.Context) (*Response, error)
ReadResponse reads the buffered response first, then normal responses
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client represents a JSON-RPC client that can make requests using any codec
func NewHTTPClient ¶
NewHTTPClient creates a new HTTP JSON-RPC client
func NewSimpleClient ¶
SimpleClient provides a simple way to create clients
func (*Client) CallWithResult ¶
CallWithResult makes a call and unmarshals the result into the provided variable
func (*Client) IsConnected ¶
IsConnected returns true if the client is connected
type ClientCodec ¶
type ClientCodec interface {
Codec
// Connect establishes a connection to the server
Connect(ctx context.Context, address string) error
}
Client defines additional methods needed for client-side codec operations
type Codec ¶
type Codec interface {
// WriteRequest writes a JSON-RPC request to the underlying transport
WriteRequest(ctx context.Context, req *Request) error
// ReadRequest reads a JSON-RPC request from the underlying transport
ReadRequest(ctx context.Context) (*Request, error)
// WriteResponse writes a JSON-RPC response to the underlying transport
WriteResponse(ctx context.Context, resp *Response) error
// ReadResponse reads a JSON-RPC response from the underlying transport
ReadResponse(ctx context.Context) (*Response, error)
// Close closes the underlying transport connection
Close() error
// RemoteAddr returns the remote address if available
RemoteAddr() string
}
type Error ¶
type Error struct {
Code int `json:"code"`
Message string `json:"message"`
Data any `json:"data,omitempty"`
}
Error represents a JSON-RPC 2.0 error
type Handler ¶
Handler represents a function that handles JSON-RPC requests We use any to avoid circular imports - this should be cast to appropriate jsonrpc
type HttpClient ¶
type HttpClient struct {
*HttpCodec
// contains filtered or unexported fields
}
Client implements Client for HTTP clients
func NewHttpClient ¶
func NewHttpClient(client *http.Client) *HttpClient
NewClient creates a new HTTP client codec
func (*HttpClient) Connect ¶
func (c *HttpClient) Connect(ctx context.Context, address string) error
Connect sets the server address for HTTP requests
func (*HttpClient) GetAddress ¶
func (c *HttpClient) GetAddress() string
GetAddress returns the connected address
func (*HttpClient) IsConnected ¶
func (c *HttpClient) IsConnected() bool
IsConnected returns true if the client has an address set
type HttpCodec ¶
type HttpCodec struct {
// contains filtered or unexported fields
}
Codec implements the Codec interface for HTTP connections
func NewHttpCodec ¶
New creates a new HTTP codec for client use
func NewRequestHttpCodec ¶
func NewRequestHttpCodec(w http.ResponseWriter, r *http.Request) *HttpCodec
NewRequestHttpCodec creates a new HTTP codec for handling a single request/response
func (*HttpCodec) ReadRequest ¶
ReadRequest reads a JSON-RPC request from HTTP request body
func (*HttpCodec) ReadResponse ¶
ReadResponse reads a JSON-RPC response from HTTP response
func (*HttpCodec) RemoteAddr ¶
RemoteAddr returns the remote address from the HTTP request
func (*HttpCodec) WriteRequest ¶
WriteRequest writes a JSON-RPC request via HTTP POST
type HttpServer ¶
type HttpServer struct {
// contains filtered or unexported fields
}
HttpServer implements Server for HTTP servers
func NewHttpServer ¶
func NewHttpServer(address, path string, handlers map[string]Handler) *HttpServer
HttpServer creates a new HTTP server codec
func (*HttpServer) Accept ¶
func (c *HttpServer) Accept(ctx context.Context) (Codec, error)
Accept starts the HTTP server and waits for connections
func (*HttpServer) ListenAndServe ¶
func (c *HttpServer) ListenAndServe() error
ListenAndServe starts the HTTP server
func (*HttpServer) ListenAndServeContext ¶
func (c *HttpServer) ListenAndServeContext(ctx context.Context) error
ListenAndServeContext starts the HTTP server with context
func (*HttpServer) ReadRequest ¶
func (c *HttpServer) ReadRequest(ctx context.Context) (any, error)
func (*HttpServer) ReadResponse ¶
func (c *HttpServer) ReadResponse(ctx context.Context) (any, error)
func (*HttpServer) RemoteAddr ¶
func (c *HttpServer) RemoteAddr() string
RemoteAddr returns the server address
func (*HttpServer) WriteRequest ¶
func (c *HttpServer) WriteRequest(ctx context.Context, req any) error
WriteRequest, ReadRequest, WriteResponse, ReadResponse are not used in server mode
func (*HttpServer) WriteResponse ¶
func (c *HttpServer) WriteResponse(ctx context.Context, resp any) error
type Request ¶
type Request struct {
JSONRPC string `json:"jsonrpc"`
Method string `json:"method"`
Params json.RawMessage `json:"params,omitempty"`
ID any `json:"id,omitempty"`
}
Request represents a JSON-RPC 2.0 request
func NewNotification ¶
NewNotification creates a new JSON-RPC notification (request without ID)
func NewRequest ¶
NewRequest creates a new JSON-RPC request
func (*Request) IsNotification ¶
IsNotification returns true if the request is a notification (has no ID)
type Response ¶
type Response struct {
JSONRPC string `json:"jsonrpc"`
Result json.RawMessage `json:"result,omitempty"`
Error *Error `json:"error,omitempty"`
ID any `json:"id"`
}
Response represents a JSON-RPC 2.0 response
func NewErrorResponse ¶
NewErrorResponse creates a new JSON-RPC error response
func NewResponse ¶
NewResponse creates a new JSON-RPC response
type ServerCodec ¶
type ServerCodec interface {
Codec
// Accept accepts new connections (for connection-oriented protocols)
Accept(ctx context.Context) (Codec, error)
}
Server defines additional methods needed for server-side codec operations
type TcpClient ¶
type TcpClient struct {
*TcpCodec
// contains filtered or unexported fields
}
Client implements Client for TCP clients
func (*TcpClient) GetAddress ¶
GetAddress returns the connected address
func (*TcpClient) IsConnected ¶
IsConnected returns true if the client is connected
type TcpCodec ¶
type TcpCodec struct {
// contains filtered or unexported fields
}
Codec implements the Codec interface for TCP connections
func (*TcpCodec) ReadRequest ¶
ReadRequest reads a JSON-RPC request from the TCP connection
func (*TcpCodec) ReadResponse ¶
ReadResponse reads a JSON-RPC response from the TCP connection
func (*TcpCodec) RemoteAddr ¶
RemoteAddr returns the remote address of the TCP connection
func (*TcpCodec) WriteRequest ¶
WriteRequest writes a JSON-RPC request to the TCP connection
type TcpServer ¶
type TcpServer struct {
// contains filtered or unexported fields
}
Server implements Server for TCP servers
func NewTcpServer ¶
NewServer creates a new TCP server codec
func (*TcpServer) ReadRequest ¶
func (*TcpServer) ReadResponse ¶
func (*TcpServer) RemoteAddr ¶
RemoteAddr returns the listener address
func (*TcpServer) WriteRequest ¶
WriteRequest, ReadRequest, WriteResponse, ReadResponse are not used in server mode but need to be implemented to satisfy the Server interface
type UdpClient ¶
type UdpClient struct {
*UdpCodec
// contains filtered or unexported fields
}
UdpClient implements ClientCodec for UDP clients
func NewUdpClientWithTimeout ¶
NewUdpClientWithTimeout creates a new UDP client codec with custom timeout
func (*UdpClient) GetAddress ¶
GetAddress returns the connected address
func (*UdpClient) IsConnected ¶
IsConnected returns true if the client is connected
func (*UdpClient) SetTimeout ¶
SetTimeout sets the timeout for client operations
type UdpCodec ¶
type UdpCodec struct {
// contains filtered or unexported fields
}
UdpCodec implements the Codec interface for UDP connections
func NewUdpCodec ¶
NewUdpCodec creates a new UDP codec with a UDP connection
func NewUdpCodecWithTimeout ¶
func NewUdpCodecWithTimeout(conn *net.UDPConn, remoteAddr *net.UDPAddr, timeout time.Duration) *UdpCodec
NewUdpCodecWithTimeout creates a new UDP codec with a custom timeout
func (*UdpCodec) ReadRequest ¶
ReadRequest reads a JSON-RPC request from the UDP connection
func (*UdpCodec) ReadResponse ¶
ReadResponse reads a JSON-RPC response from the UDP connection
func (*UdpCodec) RemoteAddr ¶
RemoteAddr returns the remote address of the UDP connection
func (*UdpCodec) SetTimeout ¶
SetTimeout sets the timeout for UDP operations
func (*UdpCodec) WriteRequest ¶
WriteRequest writes a JSON-RPC request to the UDP connection
type UdpServer ¶
type UdpServer struct {
// contains filtered or unexported fields
}
UdpServer implements ServerCodec for UDP servers
func NewUdpServer ¶
NewUdpServer creates a new UDP server codec
func NewUdpServerWithTimeout ¶
NewUdpServerWithTimeout creates a new UDP server codec with custom timeout
func (*UdpServer) Accept ¶
Accept waits for and returns a codec for handling a UDP message Since UDP is connectionless, this creates a new codec for each message
func (*UdpServer) ReadRequest ¶
func (*UdpServer) ReadResponse ¶
func (*UdpServer) RemoteAddr ¶
RemoteAddr returns the server address (for UDP server, this is the local listening address)
func (*UdpServer) SetTimeout ¶
SetTimeout sets the timeout for server operations
func (*UdpServer) WriteRequest ¶
WriteRequest, ReadRequest, WriteResponse, ReadResponse are not used in server mode but need to be implemented to satisfy the ServerCodec interface