Skip to content

Commit

Permalink
Reduce the API and remove the need for servers to interact with the R…
Browse files Browse the repository at this point in the history
…esponse type at all. Remove method name and Error constraints that were not officially in the spec
  • Loading branch information
AdamSLevy committed Dec 3, 2018
1 parent 053d38d commit eaf463d
Show file tree
Hide file tree
Showing 11 changed files with 281 additions and 332 deletions.
47 changes: 25 additions & 22 deletions doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,46 @@
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.

// Package jsonrpc2 is a conforming implementation of the JSON-RPC 2.0 protocol
// designed to provide a minimalist API, avoid unnecessary unmarshaling and
// memory allocation, and work with any http server framework that uses
// http.Handler. It strives to conform very strictly to the official
// specification: https://www.jsonrpc.org.
// Package jsonrpc2 is a complete and strictly conforming implementation of the
// JSON-RPC 2.0 protocol for both clients and servers.
//
// This package provides types for Requests and Responses, and a function to
// return a http.HandlerFunc that calls the MethodFuncs in a given MethodMap.
// The http.HandlerFunc will recover from any MethodFunc panics and will always
// respond with a valid JSON RPC Response, unless of course the Request did not
// have an ID, and thus was a Notification.
// https://www.jsonrpc.org.
//
// Client
//
// Clients use the provided types, optionally along with their own custom data
// types for making Requests and parsing Responses. The Request and Response
// types are defined so that they can accept any valid types for "id",
// "params", and "result".
//
// Clients can use the Request, Response, and Error types with the json and
// http packages to make HTTP JSON-RPC 2.0 calls and parse their responses.
// reqBytes, _ := json.Marshal(jsonrpc2.NewRequest("subtract", 0, []int{5, 1}))
// httpResp, _ := http.Post("www.example.com", "application/json",
// bytes.NewReader(reqBytes))
// respBytes, _ := ioutil.ReadAll(httpResp.Body)
// response := jsonrpc2.Response{Result: MyCustomResultType{}}
// response := jsonrpc2.Response{Result: &MyCustomResultType{}}
// json.Unmarshal(respBytes, &response)
//
// Server
//
// Servers must implement their RPC method functions to match the MethodFunc
// type, and relate a name to the method using a MethodMap.
// var func versionMethod(p json.RawMessage) jsonrpc2.Response {
// Servers define their own MethodFuncs and associate them with a method name
// in a MethodMap. Passing the MethodMap to HTTPRequestHandler() will return a
// corresponding http.Handler which can be used with an http.Server. The
// http.Handler handles both batch and single requests, catches all protocol
// errors, and recovers from any panics or invalid return values from the user
// provided MethodFunc. MethodFuncs only need to catch errors related to their
// function such as Invalid Params or any user defined errors for the RPC
// method.
//
// func versionMethod(p json.RawMessage) interface{} {
// if p != nil {
// return jsonrpc2.NewInvalidParamsErrorResponse(nil)
// return jsonrpc2.NewInvalidParamsError("no params accepted")
// }
// return jsonrpc2.NewResponse("0.0.0")
// return "0.0.0"
// }
// var methods = jsonrpc2.MethodMap{"version": versionMethod}
// func StartServer() {
// http.ListenAndServe(":8080", jsonrpc2.HTTPRequestHandler(methods))
// }
// var methods = jsonrpc2.MethodMap{"version", versionMethod}
// Read the documentation for MethodFunc and MethodMap for more information.
//
// Finally generate an http.HandlerFunc for your MethodMap and start your
// server.
// http.ListenAndServe(":8080", jsonrpc2.HTTPRequestHandler(methods))
package jsonrpc2
15 changes: 12 additions & 3 deletions error.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

package jsonrpc2

// Error represents the "error" field in a JSON-RPC 2.0 Response object.
// Error represents a JSON-RPC 2.0 Error object, which is used in the Response
// object.
type Error struct {
Code ErrorCode `json:"code"`
Message string `json:"message"`
Expand All @@ -31,12 +32,13 @@ const (
InternalErrorMessage = "Internal error"
)

// IsReserved returns true if c is within the reserved error code range.
// IsReserved returns true if c is within the reserved error code range:
// [LowestReservedErrorCode, HighestReservedErrorCode].
func (c ErrorCode) IsReserved() bool {
return LowestReservedErrorCode <= c && c <= HighestReservedErrorCode
}

// Official Errors
// Official JSON-RPC 2.0 Errors
var (
// ParseError is returned to the client if a JSON is not well formed.
ParseError = NewError(ParseErrorCode, ParseErrorMessage, nil)
Expand All @@ -59,3 +61,10 @@ var (
func NewError(code ErrorCode, message string, data interface{}) Error {
return Error{Code: code, Message: message, Data: data}
}

// NewInvalidParamsError returns an InvalidParams Error with the given data.
func NewInvalidParamsError(data interface{}) Error {
err := InvalidParams
err.Data = data
return err
}
4 changes: 2 additions & 2 deletions example_funcs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"io/ioutil"
"net/http"

"github.com/AdamSLevy/jsonrpc2/v8"
"github.com/AdamSLevy/jsonrpc2/v9"
)

// Use the http and json packages to send a Request object.
Expand All @@ -24,7 +24,7 @@ func ExampleRequest() {
// Any panic will return InternalError to the user if the call was a request
// and not a Notification.
func ExampleMethodFunc_panic() {
var _ jsonrpc2.MethodFunc = func(params json.RawMessage) jsonrpc2.Response {
var _ jsonrpc2.MethodFunc = func(params json.RawMessage) interface{} {
panic("don't worry, jsonrpc2 will recover you and return an internal error")
}
}
31 changes: 15 additions & 16 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
"io/ioutil"
"net/http"

jrpc "github.com/AdamSLevy/jsonrpc2/v8"
jrpc "github.com/AdamSLevy/jsonrpc2/v9"
)

var endpoint = "http://localhost:18888"
Expand Down Expand Up @@ -51,43 +51,42 @@ func postBytes(req string) {
}

// The RPC methods called in the JSON-RPC 2.0 specification examples.
func subtract(params json.RawMessage) jrpc.Response {
func subtract(params json.RawMessage) interface{} {
// Parse either a params array of numbers or named numbers params.
var a []float64
if err := json.Unmarshal(params, &a); err == nil {
if len(a) != 2 {
return jrpc.NewInvalidParamsErrorResponse(
"Invalid number of array params")
return jrpc.NewInvalidParamsError("Invalid number of array params")
}
return jrpc.NewResponse(a[0] - a[1])
return a[0] - a[1]
}
var p struct {
Subtrahend *float64
Minuend *float64
}
if err := json.Unmarshal(params, &p); err != nil ||
p.Subtrahend == nil || p.Minuend == nil {
return jrpc.NewInvalidParamsErrorResponse("Required fields " +
`"subtrahend" and "minuend" must be valid numbers.`)
return jrpc.NewInvalidParamsError(`Required fields "subtrahend" and ` +
`"minuend" must be valid numbers.`)
}
return jrpc.NewResponse(*p.Minuend - *p.Subtrahend)
return *p.Minuend - *p.Subtrahend
}
func sum(params json.RawMessage) jrpc.Response {
func sum(params json.RawMessage) interface{} {
var p []float64
if err := json.Unmarshal(params, &p); err != nil {
return jrpc.NewInvalidParamsErrorResponse(nil)
return jrpc.NewInvalidParamsError(err)
}
sum := float64(0)
for _, x := range p {
sum += x
}
return jrpc.NewResponse(sum)
return sum
}
func notifyHello(_ json.RawMessage) jrpc.Response {
return jrpc.NewResponse("")
func notifyHello(_ json.RawMessage) interface{} {
return ""
}
func getData(_ json.RawMessage) jrpc.Response {
return jrpc.NewResponse([]interface{}{"hello", 5})
func getData(_ json.RawMessage) interface{} {
return []interface{}{"hello", 5}
}

// This example makes all of the calls from the examples in the JSON-RPC 2.0
Expand All @@ -103,7 +102,7 @@ func Example() {
"get_data": getData,
}
handler := jrpc.HTTPRequestHandler(methods)
jrpc.DebugMethodFunc = false
jrpc.DebugMethodFunc = true
http.ListenAndServe(":18888", handler)
}()

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module github.com/AdamSLevy/jsonrpc2/v8
module github.com/AdamSLevy/jsonrpc2/v9

require (
github.com/davecgh/go-spew v1.1.1 // indirect
Expand Down
Loading

0 comments on commit eaf463d

Please sign in to comment.