github.com/99designs/gqlgen@v0.17.45/handler/handler.go (about) 1 package handler 2 3 import ( 4 "context" 5 "net/http" 6 "time" 7 8 "github.com/gorilla/websocket" 9 10 "github.com/99designs/gqlgen/graphql" 11 "github.com/99designs/gqlgen/graphql/handler" 12 "github.com/99designs/gqlgen/graphql/handler/extension" 13 "github.com/99designs/gqlgen/graphql/handler/lru" 14 "github.com/99designs/gqlgen/graphql/handler/transport" 15 "github.com/99designs/gqlgen/graphql/playground" 16 ) 17 18 // Deprecated: switch to graphql/handler.New 19 func GraphQL(exec graphql.ExecutableSchema, options ...Option) http.HandlerFunc { 20 var cfg Config 21 cfg.cacheSize = 1000 22 23 for _, option := range options { 24 option(&cfg) 25 } 26 27 srv := handler.New(exec) 28 29 srv.AddTransport(transport.Websocket{ 30 Upgrader: cfg.upgrader, 31 InitFunc: cfg.websocketInitFunc, 32 KeepAlivePingInterval: cfg.connectionKeepAlivePingInterval, 33 PingPongInterval: cfg.connectionPingPongInterval, 34 }) 35 srv.AddTransport(transport.Options{}) 36 srv.AddTransport(transport.GET{}) 37 srv.AddTransport(transport.POST{}) 38 srv.AddTransport(transport.MultipartForm{ 39 MaxUploadSize: cfg.uploadMaxSize, 40 MaxMemory: cfg.uploadMaxMemory, 41 }) 42 43 if cfg.cacheSize != 0 { 44 srv.SetQueryCache(lru.New(cfg.cacheSize)) 45 } 46 if cfg.recover != nil { 47 srv.SetRecoverFunc(cfg.recover) 48 } 49 if cfg.errorPresenter != nil { 50 srv.SetErrorPresenter(cfg.errorPresenter) 51 } 52 for _, hook := range cfg.fieldHooks { 53 srv.AroundFields(hook) 54 } 55 for _, hook := range cfg.requestHooks { 56 srv.AroundResponses(hook) 57 } 58 if cfg.complexityLimit != 0 { 59 srv.Use(extension.FixedComplexityLimit(cfg.complexityLimit)) 60 } else if cfg.complexityLimitFunc != nil { 61 srv.Use(&extension.ComplexityLimit{ 62 Func: func(ctx context.Context, rc *graphql.OperationContext) int { 63 return cfg.complexityLimitFunc(graphql.WithOperationContext(ctx, rc)) 64 }, 65 }) 66 } 67 if !cfg.disableIntrospection { 68 srv.Use(extension.Introspection{}) 69 } 70 if cfg.apqCache != nil { 71 srv.Use(extension.AutomaticPersistedQuery{Cache: apqAdapter{cfg.apqCache}}) 72 } 73 return srv.ServeHTTP 74 } 75 76 // Deprecated: switch to graphql/handler.New 77 type Config struct { 78 cacheSize int 79 upgrader websocket.Upgrader 80 websocketInitFunc transport.WebsocketInitFunc 81 connectionKeepAlivePingInterval time.Duration 82 connectionPingPongInterval time.Duration 83 recover graphql.RecoverFunc 84 errorPresenter graphql.ErrorPresenterFunc 85 fieldHooks []graphql.FieldMiddleware 86 requestHooks []graphql.ResponseMiddleware 87 complexityLimit int 88 complexityLimitFunc func(ctx context.Context) int 89 disableIntrospection bool 90 uploadMaxMemory int64 91 uploadMaxSize int64 92 apqCache PersistedQueryCache 93 } 94 95 // Deprecated: switch to graphql/handler.New 96 type Option func(cfg *Config) 97 98 // Deprecated: switch to graphql/handler.New 99 func WebsocketUpgrader(upgrader websocket.Upgrader) Option { 100 return func(cfg *Config) { 101 cfg.upgrader = upgrader 102 } 103 } 104 105 // Deprecated: switch to graphql/handler.New 106 func RecoverFunc(recover graphql.RecoverFunc) Option { 107 return func(cfg *Config) { 108 cfg.recover = recover 109 } 110 } 111 112 // ErrorPresenter transforms errors found while resolving into errors that will be returned to the user. It provides 113 // a good place to add any extra fields, like error.type, that might be desired by your frontend. Check the default 114 // implementation in graphql.DefaultErrorPresenter for an example. 115 // Deprecated: switch to graphql/handler.New 116 func ErrorPresenter(f graphql.ErrorPresenterFunc) Option { 117 return func(cfg *Config) { 118 cfg.errorPresenter = f 119 } 120 } 121 122 // IntrospectionEnabled = false will forbid clients from calling introspection endpoints. Can be useful in prod when you don't 123 // want clients introspecting the full schema. 124 // Deprecated: switch to graphql/handler.New 125 func IntrospectionEnabled(enabled bool) Option { 126 return func(cfg *Config) { 127 cfg.disableIntrospection = !enabled 128 } 129 } 130 131 // ComplexityLimit sets a maximum query complexity that is allowed to be executed. 132 // If a query is submitted that exceeds the limit, a 422 status code will be returned. 133 // Deprecated: switch to graphql/handler.New 134 func ComplexityLimit(limit int) Option { 135 return func(cfg *Config) { 136 cfg.complexityLimit = limit 137 } 138 } 139 140 // ComplexityLimitFunc allows you to define a function to dynamically set the maximum query complexity that is allowed 141 // to be executed. 142 // If a query is submitted that exceeds the limit, a 422 status code will be returned. 143 // Deprecated: switch to graphql/handler.New 144 func ComplexityLimitFunc(complexityLimitFunc func(ctx context.Context) int) Option { 145 return func(cfg *Config) { 146 cfg.complexityLimitFunc = complexityLimitFunc 147 } 148 } 149 150 // ResolverMiddleware allows you to define a function that will be called around every resolver, 151 // useful for logging. 152 // Deprecated: switch to graphql/handler.New 153 func ResolverMiddleware(middleware graphql.FieldMiddleware) Option { 154 return func(cfg *Config) { 155 cfg.fieldHooks = append(cfg.fieldHooks, middleware) 156 } 157 } 158 159 // RequestMiddleware allows you to define a function that will be called around the root request, 160 // after the query has been parsed. This is useful for logging 161 // Deprecated: switch to graphql/handler.New 162 func RequestMiddleware(middleware graphql.ResponseMiddleware) Option { 163 return func(cfg *Config) { 164 cfg.requestHooks = append(cfg.requestHooks, middleware) 165 } 166 } 167 168 // WebsocketInitFunc is called when the server receives connection init message from the client. 169 // This can be used to check initial payload to see whether to accept the websocket connection. 170 // Deprecated: switch to graphql/handler.New 171 func WebsocketInitFunc(websocketInitFunc transport.WebsocketInitFunc) Option { 172 return func(cfg *Config) { 173 cfg.websocketInitFunc = websocketInitFunc 174 } 175 } 176 177 // CacheSize sets the maximum size of the query cache. 178 // If size is less than or equal to 0, the cache is disabled. 179 // Deprecated: switch to graphql/handler.New 180 func CacheSize(size int) Option { 181 return func(cfg *Config) { 182 cfg.cacheSize = size 183 } 184 } 185 186 // UploadMaxSize sets the maximum number of bytes used to parse a request body 187 // as multipart/form-data. 188 // Deprecated: switch to graphql/handler.New 189 func UploadMaxSize(size int64) Option { 190 return func(cfg *Config) { 191 cfg.uploadMaxSize = size 192 } 193 } 194 195 // UploadMaxMemory sets the maximum number of bytes used to parse a request body 196 // as multipart/form-data in memory, with the remainder stored on disk in 197 // temporary files. 198 // Deprecated: switch to graphql/handler.New 199 func UploadMaxMemory(size int64) Option { 200 return func(cfg *Config) { 201 cfg.uploadMaxMemory = size 202 } 203 } 204 205 // WebsocketKeepAliveDuration allows you to reconfigure the keepalive behavior. 206 // By default, keepalive is enabled with a DefaultConnectionKeepAlivePingInterval 207 // duration. Set handler.connectionKeepAlivePingInterval = 0 to disable keepalive 208 // altogether. 209 // Deprecated: switch to graphql/handler.New 210 func WebsocketKeepAliveDuration(duration time.Duration) Option { 211 return func(cfg *Config) { 212 cfg.connectionKeepAlivePingInterval = duration 213 } 214 } 215 216 func WebsocketPingPongDuration(duration time.Duration) Option { 217 return func(cfg *Config) { 218 cfg.connectionPingPongInterval = duration 219 } 220 } 221 222 // Add cache that will hold queries for automatic persisted queries (APQ) 223 // Deprecated: switch to graphql/handler.New 224 func EnablePersistedQueryCache(cache PersistedQueryCache) Option { 225 return func(cfg *Config) { 226 cfg.apqCache = cache 227 } 228 } 229 230 func GetInitPayload(ctx context.Context) transport.InitPayload { 231 return transport.GetInitPayload(ctx) 232 } 233 234 type apqAdapter struct { 235 PersistedQueryCache 236 } 237 238 func (a apqAdapter) Get(ctx context.Context, key string) (value interface{}, ok bool) { 239 return a.PersistedQueryCache.Get(ctx, key) 240 } 241 242 func (a apqAdapter) Add(ctx context.Context, key string, value interface{}) { 243 a.PersistedQueryCache.Add(ctx, key, value.(string)) 244 } 245 246 type PersistedQueryCache interface { 247 Add(ctx context.Context, hash string, query string) 248 Get(ctx context.Context, hash string) (string, bool) 249 } 250 251 // Deprecated: use playground.Handler instead 252 func Playground(title string, endpoint string) http.HandlerFunc { 253 return playground.Handler(title, endpoint) 254 } 255 256 // Deprecated: use transport.InitPayload instead 257 type InitPayload = transport.InitPayload