-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
handler.go
247 lines (218 loc) · 7.92 KB
/
handler.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
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
package handler
import (
"context"
"net/http"
"time"
"github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/graphql/handler"
"github.com/99designs/gqlgen/graphql/handler/extension"
"github.com/99designs/gqlgen/graphql/handler/lru"
"github.com/99designs/gqlgen/graphql/handler/transport"
"github.com/99designs/gqlgen/graphql/playground"
"github.com/gorilla/websocket"
)
// Deprecated: switch to graphql/handler.New
func GraphQL(exec graphql.ExecutableSchema, options ...Option) http.HandlerFunc {
var cfg Config
cfg.cacheSize = 1000
for _, option := range options {
option(&cfg)
}
srv := handler.New(exec)
srv.AddTransport(transport.Websocket{
Upgrader: cfg.upgrader,
InitFunc: cfg.websocketInitFunc,
KeepAlivePingInterval: cfg.connectionKeepAlivePingInterval,
})
srv.AddTransport(transport.Options{})
srv.AddTransport(transport.GET{})
srv.AddTransport(transport.POST{})
srv.AddTransport(transport.MultipartForm{
MaxUploadSize: cfg.uploadMaxSize,
MaxMemory: cfg.uploadMaxMemory,
})
if cfg.cacheSize != 0 {
srv.SetQueryCache(lru.New(cfg.cacheSize))
}
if cfg.recover != nil {
srv.SetRecoverFunc(cfg.recover)
}
if cfg.errorPresenter != nil {
srv.SetErrorPresenter(cfg.errorPresenter)
}
for _, hook := range cfg.fieldHooks {
srv.AroundFields(hook)
}
for _, hook := range cfg.requestHooks {
srv.AroundResponses(hook)
}
if cfg.complexityLimit != 0 {
srv.Use(extension.FixedComplexityLimit(cfg.complexityLimit))
} else if cfg.complexityLimitFunc != nil {
srv.Use(&extension.ComplexityLimit{
Func: func(ctx context.Context, rc *graphql.OperationContext) int {
return cfg.complexityLimitFunc(graphql.WithOperationContext(ctx, rc))
},
})
}
if !cfg.disableIntrospection {
srv.Use(extension.Introspection{})
}
if cfg.apqCache != nil {
srv.Use(extension.AutomaticPersistedQuery{Cache: apqAdapter{cfg.apqCache}})
}
return srv.ServeHTTP
}
// Deprecated: switch to graphql/handler.New
type Config struct {
cacheSize int
upgrader websocket.Upgrader
websocketInitFunc transport.WebsocketInitFunc
connectionKeepAlivePingInterval time.Duration
recover graphql.RecoverFunc
errorPresenter graphql.ErrorPresenterFunc
fieldHooks []graphql.FieldMiddleware
requestHooks []graphql.ResponseMiddleware
complexityLimit int
complexityLimitFunc func(ctx context.Context) int
disableIntrospection bool
uploadMaxMemory int64
uploadMaxSize int64
apqCache PersistedQueryCache
}
// Deprecated: switch to graphql/handler.New
type Option func(cfg *Config)
// Deprecated: switch to graphql/handler.New
func WebsocketUpgrader(upgrader websocket.Upgrader) Option {
return func(cfg *Config) {
cfg.upgrader = upgrader
}
}
// Deprecated: switch to graphql/handler.New
func RecoverFunc(recover graphql.RecoverFunc) Option {
return func(cfg *Config) {
cfg.recover = recover
}
}
// ErrorPresenter transforms errors found while resolving into errors that will be returned to the user. It provides
// a good place to add any extra fields, like error.type, that might be desired by your frontend. Check the default
// implementation in graphql.DefaultErrorPresenter for an example.
// Deprecated: switch to graphql/handler.New
func ErrorPresenter(f graphql.ErrorPresenterFunc) Option {
return func(cfg *Config) {
cfg.errorPresenter = f
}
}
// IntrospectionEnabled = false will forbid clients from calling introspection endpoints. Can be useful in prod when you dont
// want clients introspecting the full schema.
// Deprecated: switch to graphql/handler.New
func IntrospectionEnabled(enabled bool) Option {
return func(cfg *Config) {
cfg.disableIntrospection = !enabled
}
}
// ComplexityLimit sets a maximum query complexity that is allowed to be executed.
// If a query is submitted that exceeds the limit, a 422 status code will be returned.
// Deprecated: switch to graphql/handler.New
func ComplexityLimit(limit int) Option {
return func(cfg *Config) {
cfg.complexityLimit = limit
}
}
// ComplexityLimitFunc allows you to define a function to dynamically set the maximum query complexity that is allowed
// to be executed.
// If a query is submitted that exceeds the limit, a 422 status code will be returned.
// Deprecated: switch to graphql/handler.New
func ComplexityLimitFunc(complexityLimitFunc func(ctx context.Context) int) Option {
return func(cfg *Config) {
cfg.complexityLimitFunc = complexityLimitFunc
}
}
// ResolverMiddleware allows you to define a function that will be called around every resolver,
// useful for logging.
// Deprecated: switch to graphql/handler.New
func ResolverMiddleware(middleware graphql.FieldMiddleware) Option {
return func(cfg *Config) {
cfg.fieldHooks = append(cfg.fieldHooks, middleware)
}
}
// RequestMiddleware allows you to define a function that will be called around the root request,
// after the query has been parsed. This is useful for logging
// Deprecated: switch to graphql/handler.New
func RequestMiddleware(middleware graphql.ResponseMiddleware) Option {
return func(cfg *Config) {
cfg.requestHooks = append(cfg.requestHooks, middleware)
}
}
// WebsocketInitFunc is called when the server receives connection init message from the client.
// This can be used to check initial payload to see whether to accept the websocket connection.
// Deprecated: switch to graphql/handler.New
func WebsocketInitFunc(websocketInitFunc transport.WebsocketInitFunc) Option {
return func(cfg *Config) {
cfg.websocketInitFunc = websocketInitFunc
}
}
// CacheSize sets the maximum size of the query cache.
// If size is less than or equal to 0, the cache is disabled.
// Deprecated: switch to graphql/handler.New
func CacheSize(size int) Option {
return func(cfg *Config) {
cfg.cacheSize = size
}
}
// UploadMaxSize sets the maximum number of bytes used to parse a request body
// as multipart/form-data.
// Deprecated: switch to graphql/handler.New
func UploadMaxSize(size int64) Option {
return func(cfg *Config) {
cfg.uploadMaxSize = size
}
}
// UploadMaxMemory sets the maximum number of bytes used to parse a request body
// as multipart/form-data in memory, with the remainder stored on disk in
// temporary files.
// Deprecated: switch to graphql/handler.New
func UploadMaxMemory(size int64) Option {
return func(cfg *Config) {
cfg.uploadMaxMemory = size
}
}
// WebsocketKeepAliveDuration allows you to reconfigure the keepalive behavior.
// By default, keepalive is enabled with a DefaultConnectionKeepAlivePingInterval
// duration. Set handler.connectionKeepAlivePingInterval = 0 to disable keepalive
// altogether.
// Deprecated: switch to graphql/handler.New
func WebsocketKeepAliveDuration(duration time.Duration) Option {
return func(cfg *Config) {
cfg.connectionKeepAlivePingInterval = duration
}
}
// Add cache that will hold queries for automatic persisted queries (APQ)
// Deprecated: switch to graphql/handler.New
func EnablePersistedQueryCache(cache PersistedQueryCache) Option {
return func(cfg *Config) {
cfg.apqCache = cache
}
}
func GetInitPayload(ctx context.Context) transport.InitPayload {
return transport.GetInitPayload(ctx)
}
type apqAdapter struct {
PersistedQueryCache
}
func (a apqAdapter) Get(ctx context.Context, key string) (value interface{}, ok bool) {
return a.PersistedQueryCache.Get(ctx, key)
}
func (a apqAdapter) Add(ctx context.Context, key string, value interface{}) {
a.PersistedQueryCache.Add(ctx, key, value.(string))
}
type PersistedQueryCache interface {
Add(ctx context.Context, hash string, query string)
Get(ctx context.Context, hash string) (string, bool)
}
// Deprecated: use playground.Handler instead
func Playground(title string, endpoint string) http.HandlerFunc {
return playground.Handler(title, endpoint)
}
// Deprecated: use transport.InitPayload instead
type InitPayload = transport.InitPayload