github.com/maeglindeveloper/gqlgen@v0.13.1-0.20210413081235-57808b12a0a0/handler/handler.go (about)

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