forked from neptulon/jsonrpc
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathctx.go
159 lines (123 loc) · 4.21 KB
/
ctx.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package jsonrpc
import (
"encoding/json"
"fmt"
"github.com/neptulon/cmap"
"github.com/neptulon/neptulon"
)
/*
* Context object definitions for Request, Response, and Notification middleware.
*/
// ReqCtx encapsulates connection, request, and reponse objects.
type ReqCtx struct {
Res interface{} // Response to be returned.
Err *ResError // Error to be returned.
Client *Client // Client connection.
id string // message ID
method string // called method
params json.RawMessage // request parameters
mw []func(ctx *ReqCtx) error
mwIndex int
session *cmap.CMap
}
func newReqCtx(id, method string, params json.RawMessage, client *neptulon.Client, mw []func(ctx *ReqCtx) error, session *cmap.CMap) *ReqCtx {
// append the last middleware to stack, which will write the response to connection, if any
mw = append(mw, func(ctx *ReqCtx) error {
if ctx.Res != nil || ctx.Err != nil {
return ctx.Client.SendResponse(ctx.id, ctx.Res, ctx.Err)
}
return nil
})
return &ReqCtx{Client: UseClient(client), id: id, method: method, params: params, mw: mw, session: session}
}
// Session is a data store for storing arbitrary data within this context to communicate with other middleware handling this message.
func (ctx *ReqCtx) Session() *cmap.CMap {
return ctx.session
}
// Params reads request parameters into given object.
// Object should be passed by reference.
func (ctx *ReqCtx) Params(v interface{}) error {
if ctx.params != nil {
if err := json.Unmarshal(ctx.params, v); err != nil {
return fmt.Errorf("cannot deserialize request params: %v", err)
}
}
return nil
}
// Next executes the next middleware in the middleware stack.
func (ctx *ReqCtx) Next() error {
ctx.mwIndex++
if ctx.mwIndex <= len(ctx.mw) {
return ctx.mw[ctx.mwIndex-1](ctx)
}
return nil
}
// NotCtx encapsulates connection and notification objects.
type NotCtx struct {
Client *Client
method string // called method
params json.RawMessage // notification parameters
mw []func(ctx *NotCtx) error
mwIndex int
session *cmap.CMap
}
func newNotCtx(method string, params json.RawMessage, client *neptulon.Client, mw []func(ctx *NotCtx) error, session *cmap.CMap) *NotCtx {
return &NotCtx{Client: UseClient(client), method: method, params: params, mw: mw, session: session}
}
// Session is a data store for storing arbitrary data within this context to communicate with other middleware handling this message.
func (ctx *NotCtx) Session() *cmap.CMap {
return ctx.session
}
// Params reads response parameters into given object.
// Object should be passed by reference.
func (ctx *NotCtx) Params(v interface{}) error {
if ctx.params != nil {
if err := json.Unmarshal(ctx.params, v); err != nil {
return fmt.Errorf("cannot deserialize notification params: %v", err)
}
}
return nil
}
// Next executes the next middleware in the middleware stack.
func (ctx *NotCtx) Next() error {
ctx.mwIndex++
if ctx.mwIndex <= len(ctx.mw) {
return ctx.mw[ctx.mwIndex-1](ctx)
}
return nil
}
// ResCtx encapsulates connection and response objects.
type ResCtx struct {
Client *Client
id string // message ID
result json.RawMessage // result parameters
err *resError // response error (if any)
mw []func(ctx *ResCtx) error
mwIndex int
session *cmap.CMap
}
func newResCtx(id string, result json.RawMessage, client *neptulon.Client, mw []func(ctx *ResCtx) error, session *cmap.CMap) *ResCtx {
return &ResCtx{Client: UseClient(client), id: id, result: result, mw: mw, session: session}
}
// Session is a data store for storing arbitrary data within this context to communicate with other middleware handling this message.
func (ctx *ResCtx) Session() *cmap.CMap {
return ctx.session
}
// Result reads response result data into given object.
// Object should be passed by reference.
func (ctx *ResCtx) Result(v interface{}) error {
if ctx.result != nil {
if err := json.Unmarshal(ctx.result, v); err != nil {
return fmt.Errorf("cannot deserialize response result: %v", err)
}
}
return nil
}
// Next executes the next middleware in the middleware stack.
func (ctx *ResCtx) Next() error {
ctx.mwIndex++
if ctx.mwIndex <= len(ctx.mw) {
return ctx.mw[ctx.mwIndex-1](ctx)
}
return nil
}