forked from eientei/wsgraphql
/
context.go
220 lines (173 loc) · 4.9 KB
/
context.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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
package wsgraphql
import (
"context"
"net/http"
"github.com/bitquery/wsgraphql/v1/mutable"
"github.com/graphql-go/graphql/language/ast"
)
type (
contextKeyRequestContextT struct{}
contextKeyOperationContextT struct{}
contextKeyOperationStoppedT struct{}
contextKeyOperationIDT struct{}
contextKeyAstT struct{}
contextKeySubscriptionT struct{}
contextKeyHTTPRequestT struct{}
contextKeyHTTPResponseWriterT struct{}
contextKeyHTTPResponseStartedT struct{}
contextKeyWebsocketConnectionT struct{}
)
var (
// ContextKeyRequestContext used to store HTTP request-scoped mutable.Context
ContextKeyRequestContext = contextKeyRequestContextT{}
// ContextKeyOperationContext used to store graphql operation-scoped mutable.Context
ContextKeyOperationContext = contextKeyOperationContextT{}
// ContextKeyOperationStopped indicates the operation was stopped on client request
ContextKeyOperationStopped = contextKeyOperationStoppedT{}
// ContextKeyOperationID indicates the operation ID
ContextKeyOperationID = contextKeyOperationIDT{}
// ContextKeyAST used to store operation's ast.Document (abstract syntax tree)
ContextKeyAST = contextKeyAstT{}
// ContextKeySubscription used to store operation subscription flag
ContextKeySubscription = contextKeySubscriptionT{}
// ContextKeyHTTPRequest used to store HTTP request
ContextKeyHTTPRequest = contextKeyHTTPRequestT{}
// ContextKeyHTTPResponseWriter used to store HTTP response
ContextKeyHTTPResponseWriter = contextKeyHTTPResponseWriterT{}
// ContextKeyHTTPResponseStarted used to indicate HTTP response already has headers sent
ContextKeyHTTPResponseStarted = contextKeyHTTPResponseStartedT{}
// ContextKeyWebsocketConnection used to store websocket connection
ContextKeyWebsocketConnection = contextKeyWebsocketConnectionT{}
)
func defaultMutcontext(ctx context.Context, mutctx mutable.Context) mutable.Context {
if mutctx != nil {
return mutctx
}
return mutable.NewMutableContext(ctx)
}
// RequestContext returns HTTP request-scoped v1.mutable context from provided context or nil if none present
func RequestContext(ctx context.Context) (mutctx mutable.Context) {
defer func() {
mutctx = defaultMutcontext(ctx, mutctx)
}()
v := ctx.Value(ContextKeyRequestContext)
if v == nil {
return nil
}
mutctx, ok := v.(mutable.Context)
if !ok {
return nil
}
return mutctx
}
// OperationContext returns graphql operation-scoped v1.mutable context from provided context or nil if none present
func OperationContext(ctx context.Context) (mutctx mutable.Context) {
defer func() {
mutctx = defaultMutcontext(ctx, mutctx)
}()
v := ctx.Value(ContextKeyOperationContext)
if v == nil {
return nil
}
mutctx, ok := v.(mutable.Context)
if !ok {
return nil
}
return mutctx
}
// ContextOperationStopped returns true if user requested operation stop
func ContextOperationStopped(ctx context.Context) bool {
v := ctx.Value(ContextKeyOperationStopped)
if v == nil {
return false
}
res, ok := v.(bool)
if !ok {
return false
}
return res
}
// ContextOperationID returns operaion ID stored in the context
func ContextOperationID(ctx context.Context) string {
v := ctx.Value(ContextKeyOperationID)
if v == nil {
return ""
}
res, ok := v.(string)
if !ok {
return ""
}
return res
}
// ContextAST returns operation's abstract syntax tree document
func ContextAST(ctx context.Context) *ast.Document {
v := ctx.Value(ContextKeyAST)
if v == nil {
return nil
}
astdoc, ok := v.(*ast.Document)
if !ok {
return nil
}
return astdoc
}
// ContextSubscription returns operation's subscription flag
func ContextSubscription(ctx context.Context) bool {
v := ctx.Value(ContextKeySubscription)
if v == nil {
return false
}
sub, ok := v.(bool)
if !ok {
return false
}
return sub
}
// ContextHTTPRequest returns http request stored in a context
func ContextHTTPRequest(ctx context.Context) *http.Request {
v := ctx.Value(ContextKeyHTTPRequest)
if v == nil {
return nil
}
req, ok := v.(*http.Request)
if !ok {
return nil
}
return req
}
// ContextHTTPResponseWriter returns http response writer stored in a context
func ContextHTTPResponseWriter(ctx context.Context) http.ResponseWriter {
v := ctx.Value(ContextKeyHTTPResponseWriter)
if v == nil {
return nil
}
req, ok := v.(http.ResponseWriter)
if !ok {
return nil
}
return req
}
// ContextHTTPResponseStarted returns true if HTTP response has already headers sent
func ContextHTTPResponseStarted(ctx context.Context) bool {
v := ctx.Value(ContextKeyHTTPResponseStarted)
if v == nil {
return false
}
val, ok := v.(bool)
if !ok {
return false
}
return val
}
// ContextWebsocketConnection returns websocket connection stored in a context
func ContextWebsocketConnection(ctx context.Context) Conn {
v := ctx.Value(ContextKeyWebsocketConnection)
if v == nil {
return nil
}
conn, ok := v.(Conn)
if !ok {
return nil
}
return conn
}