...

Text file src/github.com/go-kit/kit/transport/http/jsonrpc/README.md

Documentation: github.com/go-kit/kit/transport/http/jsonrpc

     1# JSON RPC
     2
     3[JSON RPC](http://www.jsonrpc.org) is "A light weight remote procedure call protocol". It allows for the creation of simple RPC-style APIs with human-readable messages that are front-end friendly.
     4
     5## Using JSON RPC with Go-Kit
     6Using JSON RPC and go-kit together is quite simple.
     7
     8A JSON RPC _server_ acts as an [HTTP Handler](https://godoc.org/net/http#Handler), receiving all requests to the JSON RPC's URL. The server looks at the `method` property of the [Request Object](http://www.jsonrpc.org/specification#request_object), and routes it to the corresponding code.
     9
    10Each JSON RPC _method_ is implemented as an `EndpointCodec`, a go-kit [Endpoint](https://godoc.org/github.com/go-kit/kit/endpoint#Endpoint), sandwiched between a decoder and encoder. The decoder picks apart the JSON RPC request params, which can be passed to your endpoint. The encoder receives the output from the endpoint and encodes a JSON-RPC result.
    11
    12## Example — Add Service
    13Let's say we want a service that adds two ints together. We'll serve this at `http://localhost/rpc`. So a request to our `sum` method will be a POST to `http://localhost/rpc` with a request body of:
    14
    15	{
    16	    "id": 123,
    17	    "jsonrpc": "2.0",
    18	    "method": "sum",
    19	    "params": {
    20	    	"A": 2,
    21	    	"B": 2
    22	    }
    23	}
    24
    25### `EndpointCodecMap`
    26The routing table for incoming JSON RPC requests is the `EndpointCodecMap`. The key of the map is the JSON RPC method name. Here, we're routing the `sum` method to an `EndpointCodec` wrapped around `sumEndpoint`.
    27
    28	jsonrpc.EndpointCodecMap{
    29		"sum": jsonrpc.EndpointCodec{
    30			Endpoint: sumEndpoint,
    31			Decode:   decodeSumRequest,
    32			Encode:   encodeSumResponse,
    33		},
    34	}
    35
    36### Decoder
    37	type DecodeRequestFunc func(context.Context, json.RawMessage) (request interface{}, err error)
    38
    39A `DecodeRequestFunc` is given the raw JSON from the `params` property of the Request object, _not_ the whole request object. It returns an object that will be the input to the Endpoint. For our purposes, the output should be a SumRequest, like this:
    40
    41	type SumRequest struct {
    42		A, B int
    43	}
    44
    45So here's our decoder:
    46
    47	func decodeSumRequest(ctx context.Context, msg json.RawMessage) (interface{}, error) {
    48		var req SumRequest
    49		err := json.Unmarshal(msg, &req)
    50		if err != nil {
    51			return nil, err
    52		}
    53		return req, nil
    54	}
    55
    56So our `SumRequest` will now be passed to the endpoint. Once the endpoint has done its work, we hand over to the…
    57
    58### Encoder
    59The encoder takes the output of the endpoint, and builds the raw JSON message that will form the `result` field of a [Response Object](http://www.jsonrpc.org/specification#response_object). Our result is going to be a plain int. Here's our encoder:
    60
    61	func encodeSumResponse(ctx context.Context, result interface{}) (json.RawMessage, error) {
    62		sum, ok := result.(int)
    63		if !ok {
    64			return nil, errors.New("result is not an int")
    65		}
    66		b, err := json.Marshal(sum)
    67		if err != nil {
    68			return nil, err
    69		}
    70		return b, nil
    71	}
    72
    73### Server
    74Now that we have an EndpointCodec with decoder, endpoint, and encoder, we can wire up the server:
    75
    76	handler := jsonrpc.NewServer(jsonrpc.EndpointCodecMap{
    77		"sum": jsonrpc.EndpointCodec{
    78			Endpoint: sumEndpoint,
    79			Decode:   decodeSumRequest,
    80			Encode:   encodeSumResponse,
    81		},
    82	})
    83	http.Handle("/rpc", handler)
    84	http.ListenAndServe(":80", nil)
    85
    86With all of this done, our example request above should result in a response like this:
    87
    88	{
    89	    "jsonrpc": "2.0",
    90	    "result": 4
    91	}

View as plain text