aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/99designs/gqlgen/handler
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/99designs/gqlgen/handler')
-rw-r--r--vendor/github.com/99designs/gqlgen/handler/graphql.go38
-rw-r--r--vendor/github.com/99designs/gqlgen/handler/playground.go19
-rw-r--r--vendor/github.com/99designs/gqlgen/handler/websocket.go30
3 files changed, 65 insertions, 22 deletions
diff --git a/vendor/github.com/99designs/gqlgen/handler/graphql.go b/vendor/github.com/99designs/gqlgen/handler/graphql.go
index 7c5f70cf..92a0471c 100644
--- a/vendor/github.com/99designs/gqlgen/handler/graphql.go
+++ b/vendor/github.com/99designs/gqlgen/handler/graphql.go
@@ -34,6 +34,7 @@ type Config struct {
requestHook graphql.RequestMiddleware
tracer graphql.Tracer
complexityLimit int
+ complexityLimitFunc graphql.ComplexityLimitFunc
disableIntrospection bool
connectionKeepAlivePingInterval time.Duration
}
@@ -60,11 +61,9 @@ func (c *Config) newRequestContext(es graphql.ExecutableSchema, doc *ast.QueryDo
if hook := c.tracer; hook != nil {
reqCtx.Tracer = hook
- } else {
- reqCtx.Tracer = &graphql.NopTracer{}
}
- if c.complexityLimit > 0 {
+ if c.complexityLimit > 0 || c.complexityLimitFunc != nil {
reqCtx.ComplexityLimit = c.complexityLimit
operationComplexity := complexity.Calculate(es, op, variables)
reqCtx.OperationComplexity = operationComplexity
@@ -112,6 +111,15 @@ func ComplexityLimit(limit int) Option {
}
}
+// 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.
+func ComplexityLimitFunc(complexityLimitFunc graphql.ComplexityLimitFunc) 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.
func ResolverMiddleware(middleware graphql.FieldMiddleware) Option {
@@ -243,19 +251,23 @@ func CacheSize(size int) Option {
}
}
-const DefaultCacheSize = 1000
-
-// WebsocketKeepAliveDuration allows you to reconfigure the keepAlive behavior.
-// By default, keep-alive is disabled.
+// 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.
func WebsocketKeepAliveDuration(duration time.Duration) Option {
return func(cfg *Config) {
cfg.connectionKeepAlivePingInterval = duration
}
}
+const DefaultCacheSize = 1000
+const DefaultConnectionKeepAlivePingInterval = 25 * time.Second
+
func GraphQL(exec graphql.ExecutableSchema, options ...Option) http.HandlerFunc {
cfg := &Config{
- cacheSize: DefaultCacheSize,
+ cacheSize: DefaultCacheSize,
+ connectionKeepAlivePingInterval: DefaultConnectionKeepAlivePingInterval,
upgrader: websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
@@ -269,7 +281,7 @@ func GraphQL(exec graphql.ExecutableSchema, options ...Option) http.HandlerFunc
var cache *lru.Cache
if cfg.cacheSize > 0 {
var err error
- cache, err = lru.New(DefaultCacheSize)
+ cache, err = lru.New(cfg.cacheSize)
if err != nil {
// An error is only returned for non-positive cache size
// and we already checked for that.
@@ -305,10 +317,11 @@ func (gh *graphqlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
if strings.Contains(r.Header.Get("Upgrade"), "websocket") {
- connectWs(gh.exec, w, r, gh.cfg)
+ connectWs(gh.exec, w, r, gh.cfg, gh.cache)
return
}
+ w.Header().Set("Content-Type", "application/json")
var reqParams params
switch r.Method {
case http.MethodGet:
@@ -330,7 +343,6 @@ func (gh *graphqlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
- w.Header().Set("Content-Type", "application/json")
ctx := r.Context()
@@ -379,6 +391,10 @@ func (gh *graphqlHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
}()
+ if gh.cfg.complexityLimitFunc != nil {
+ reqCtx.ComplexityLimit = gh.cfg.complexityLimitFunc(ctx)
+ }
+
if reqCtx.ComplexityLimit > 0 && reqCtx.OperationComplexity > reqCtx.ComplexityLimit {
sendErrorf(w, http.StatusUnprocessableEntity, "operation has complexity %d, which exceeds the limit of %d", reqCtx.OperationComplexity, reqCtx.ComplexityLimit)
return
diff --git a/vendor/github.com/99designs/gqlgen/handler/playground.go b/vendor/github.com/99designs/gqlgen/handler/playground.go
index f1687def..0e1ca768 100644
--- a/vendor/github.com/99designs/gqlgen/handler/playground.go
+++ b/vendor/github.com/99designs/gqlgen/handler/playground.go
@@ -11,9 +11,12 @@ var page = template.Must(template.New("graphiql").Parse(`<!DOCTYPE html>
<meta charset=utf-8/>
<meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
<link rel="shortcut icon" href="https://graphcool-playground.netlify.com/favicon.png">
- <link rel="stylesheet" href="//cdn.jsdelivr.net/npm/graphql-playground-react@{{ .version }}/build/static/css/index.css"/>
- <link rel="shortcut icon" href="//cdn.jsdelivr.net/npm/graphql-playground-react@{{ .version }}/build/favicon.png"/>
- <script src="//cdn.jsdelivr.net/npm/graphql-playground-react@{{ .version }}/build/static/js/middleware.js"></script>
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/graphql-playground-react@{{ .version }}/build/static/css/index.css"
+ integrity="{{ .cssSRI }}" crossorigin="anonymous"/>
+ <link rel="shortcut icon" href="https://cdn.jsdelivr.net/npm/graphql-playground-react@{{ .version }}/build/favicon.png"
+ integrity="{{ .faviconSRI }}" crossorigin="anonymous"/>
+ <script src="https://cdn.jsdelivr.net/npm/graphql-playground-react@{{ .version }}/build/static/js/middleware.js"
+ integrity="{{ .jsSRI }}" crossorigin="anonymous"></script>
<title>{{.title}}</title>
</head>
<body>
@@ -42,10 +45,14 @@ var page = template.Must(template.New("graphiql").Parse(`<!DOCTYPE html>
func Playground(title string, endpoint string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Add("Content-Type", "text/html")
err := page.Execute(w, map[string]string{
- "title": title,
- "endpoint": endpoint,
- "version": "1.7.8",
+ "title": title,
+ "endpoint": endpoint,
+ "version": "1.7.20",
+ "cssSRI": "sha256-cS9Vc2OBt9eUf4sykRWukeFYaInL29+myBmFDSa7F/U=",
+ "faviconSRI": "sha256-GhTyE+McTU79R4+pRO6ih+4TfsTOrpPwD8ReKFzb3PM=",
+ "jsSRI": "sha256-4QG1Uza2GgGdlBL3RCBCGtGeZB6bDbsw8OltCMGeJsA=",
})
if err != nil {
panic(err)
diff --git a/vendor/github.com/99designs/gqlgen/handler/websocket.go b/vendor/github.com/99designs/gqlgen/handler/websocket.go
index 09800c17..58f38e5d 100644
--- a/vendor/github.com/99designs/gqlgen/handler/websocket.go
+++ b/vendor/github.com/99designs/gqlgen/handler/websocket.go
@@ -12,6 +12,7 @@ import (
"github.com/99designs/gqlgen/graphql"
"github.com/gorilla/websocket"
+ "github.com/hashicorp/golang-lru"
"github.com/vektah/gqlparser"
"github.com/vektah/gqlparser/ast"
"github.com/vektah/gqlparser/gqlerror"
@@ -44,12 +45,13 @@ type wsConnection struct {
active map[string]context.CancelFunc
mu sync.Mutex
cfg *Config
+ cache *lru.Cache
keepAliveTicker *time.Ticker
initPayload InitPayload
}
-func connectWs(exec graphql.ExecutableSchema, w http.ResponseWriter, r *http.Request, cfg *Config) {
+func connectWs(exec graphql.ExecutableSchema, w http.ResponseWriter, r *http.Request, cfg *Config, cache *lru.Cache) {
ws, err := cfg.upgrader.Upgrade(w, r, http.Header{
"Sec-Websocket-Protocol": []string{"graphql-ws"},
})
@@ -65,6 +67,7 @@ func connectWs(exec graphql.ExecutableSchema, w http.ResponseWriter, r *http.Req
conn: ws,
ctx: r.Context(),
cfg: cfg,
+ cache: cache,
}
if !conn.init() {
@@ -176,10 +179,27 @@ func (c *wsConnection) subscribe(message *operationMessage) bool {
return false
}
- doc, qErr := gqlparser.LoadQuery(c.exec.Schema(), reqParams.Query)
- if qErr != nil {
- c.sendError(message.ID, qErr...)
- return true
+ var (
+ doc *ast.QueryDocument
+ cacheHit bool
+ )
+ if c.cache != nil {
+ val, ok := c.cache.Get(reqParams.Query)
+ if ok {
+ doc = val.(*ast.QueryDocument)
+ cacheHit = true
+ }
+ }
+ if !cacheHit {
+ var qErr gqlerror.List
+ doc, qErr = gqlparser.LoadQuery(c.exec.Schema(), reqParams.Query)
+ if qErr != nil {
+ c.sendError(message.ID, qErr...)
+ return true
+ }
+ if c.cache != nil {
+ c.cache.Add(reqParams.Query, doc)
+ }
}
op := doc.Operations.ForName(reqParams.OperationName)