Skip to content

Commit 30b97bd

Browse files
authored
Merge pull request #1 from space307/feature/request_id
Add passing request id through context
2 parents 441d31a + d3e6985 commit 30b97bd

File tree

8 files changed

+119
-42
lines changed

8 files changed

+119
-42
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.idea

client.go

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ package jsonrpc2
55
import (
66
"context"
77
"encoding/json"
8-
"math/rand"
98
"net/http"
9+
10+
uuid "github.com/gofrs/uuid"
1011
)
1112

1213
const (
@@ -33,10 +34,10 @@ func (e *ResponseError) Error() string {
3334
// Request represents a jsonrpc2 request.
3435
//easyjson:json
3536
type Request struct {
36-
Version string `json:"jsonrpc"`
37-
Method string `json:"method"`
38-
Params interface{} `json:"params"`
39-
Id uint64 `json:"id"`
37+
Version string `json:"jsonrpc"`
38+
Method string `json:"method"`
39+
Params interface{} `json:"params"`
40+
Id *json.RawMessage `json:"id"`
4041
}
4142

4243
// Request represents a jsonrpc2 response.
@@ -45,6 +46,7 @@ type Response struct {
4546
Version string `json:"jsonrpc"`
4647
Result *json.RawMessage `json:"result"`
4748
Error *json.RawMessage `json:"error"`
49+
Id *json.RawMessage `json:"id"`
4850
}
4951

5052
type (
@@ -85,7 +87,20 @@ func NewClient(rpcEndpointURL string, options ...clientOption) Client {
8587

8688
// Call makes and does jsonrpc2 request.
8789
func (c *client) Call(ctx context.Context, methodName string, params interface{}, result interface{}) error {
88-
encodedReq, err := encodeRequest(methodName, params)
90+
requestID, _ := RequestIDFromContext(ctx)
91+
92+
if requestID == nil {
93+
reqUUID, err := uuid.NewV4()
94+
if err != nil {
95+
return err
96+
}
97+
98+
// We do not use json.Marshal because we know the json representation of a string.
99+
requestIDVal := json.RawMessage("\"" + reqUUID.String() + "\"")
100+
requestID = &requestIDVal
101+
}
102+
103+
encodedReq, err := encodeRequest(requestID, methodName, params)
89104
if err != nil {
90105
return err
91106
}
@@ -98,12 +113,12 @@ func (c *client) Call(ctx context.Context, methodName string, params interface{}
98113
return decodeResponse(resp, result)
99114
}
100115

101-
func encodeRequest(method string, args interface{}) ([]byte, error) {
116+
func encodeRequest(id *json.RawMessage, method string, args interface{}) ([]byte, error) {
102117
return json.Marshal(&Request{
103118
Version: protocolVersionStr,
104119
Method: method,
105120
Params: args,
106-
Id: uint64(rand.Int63()),
121+
Id: id,
107122
})
108123
}
109124

@@ -131,4 +146,4 @@ func decodeResponse(r []byte, reply interface{}) error {
131146
}
132147

133148
return json.Unmarshal(*resp.Result, reply)
134-
}
149+
}

client_easyjson.go

Lines changed: 55 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client_server_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package jsonrpc2
22

33
import (
44
"context"
5+
56
"github.com/semrush/zenrpc"
67
)
78

@@ -18,6 +19,5 @@ func (TestService) Divide(ctx context.Context, a int, b int) (result float32, er
1819
if b == 0 {
1920
return 0, zenrpc.NewStringError(-32500, "Could not divide to zero")
2021
}
21-
return float32(a)/float32(b), nil
22+
return float32(a) / float32(b), nil
2223
}
23-

client_test.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ package jsonrpc2
33
import (
44
"context"
55
"fmt"
6-
"github.com/semrush/zenrpc"
7-
"github.com/stretchr/testify/assert"
86
"net/http"
97
"net/http/httptest"
108
"os"
119
"testing"
10+
11+
"github.com/semrush/zenrpc"
12+
"github.com/stretchr/testify/assert"
1213
)
1314

1415
var serverURL string
@@ -29,8 +30,8 @@ func Test_client_Call_Sum_Ok(t *testing.T) {
2930
client := NewClient(fmt.Sprintf("%s/rpc", serverURL))
3031
var val int
3132
err := client.Call(context.Background(), "Sum", struct {
32-
A,B int
33-
}{1,2}, &val)
33+
A, B int
34+
}{1, 2}, &val)
3435
assert.NoError(t, err)
3536
assert.Equal(t, 3, val)
3637
}
@@ -39,8 +40,8 @@ func Test_client_Call_Div_Ok(t *testing.T) {
3940
client := NewClient(fmt.Sprintf("%s/rpc", serverURL))
4041
var val int
4142
err := client.Call(context.Background(), "Divide", struct {
42-
A,B int
43-
}{4,2}, &val)
43+
A, B int
44+
}{4, 2}, &val)
4445
assert.NoError(t, err)
4546
assert.Equal(t, 2, val)
4647
}
@@ -49,8 +50,8 @@ func Test_client_Call_Div_Fail(t *testing.T) {
4950
client := NewClient(fmt.Sprintf("%s/rpc", serverURL))
5051
var val int
5152
err := client.Call(context.Background(), "Divide", struct {
52-
A,B int
53-
}{4,0}, &val)
53+
A, B int
54+
}{4, 0}, &val)
5455
assert.Error(t, err)
5556
assert.Zero(t, val)
5657
}

context.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package jsonrpc2
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
)
7+
8+
// key is the unique and unexported ctx key for the jsonrpc package.
9+
type key int
10+
11+
// keyRequestID is particular ctx key for request id field.
12+
var keyRequestID key
13+
14+
// WithRequestID returns a new Context that carries id.
15+
func WithRequestID(ctx context.Context, id *json.RawMessage) context.Context {
16+
return context.WithValue(ctx, keyRequestID, id)
17+
}
18+
19+
// RequestIDFromContext returns the id value stored in ctx, if any.
20+
func RequestIDFromContext(ctx context.Context) (*json.RawMessage, bool) {
21+
u, ok := ctx.Value(keyRequestID).(*json.RawMessage)
22+
return u, ok
23+
}

go.mod

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
module github.com/cv21/jsonrpc2
1+
module github.com/space307/jsonrpc2
22

33
go 1.12
44

55
require (
6+
github.com/gofrs/uuid v3.2.0+incompatible
67
github.com/gorilla/websocket v1.4.1 // indirect
78
github.com/mailru/easyjson v0.7.0
8-
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
9-
github.com/modern-go/reflect2 v1.0.1 // indirect
109
github.com/prometheus/client_golang v1.1.0 // indirect
1110
github.com/semrush/zenrpc v1.1.1
1211
github.com/stretchr/testify v1.3.0

go.sum

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
1111
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
1212
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
1313
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
14+
github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
15+
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
1416
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
1517
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
1618
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -72,5 +74,6 @@ golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3 h1:4y9KwBHBgBNwDbtu44R5o1fdO
7274
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
7375
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
7476
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
77+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
7578
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
7679
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

0 commit comments

Comments
 (0)