Documentation
¶
Overview ¶
Package handler implements an HTTP handler to process GraphQL queries (and mutations/subscriptions) given an instance of a query struct (and optionally mutation and subscription structs) and a corresponding GraphQL schema. The schema is typically generated (by the schema package) using the same struct(s).
Index ¶
- Variables
- func FixNumbers(val interface{}) interface{}
- func FuncCache(on bool) func(*Handler)
- func InitialTimeout(timeout time.Duration) func(*Handler)
- func New(schemaStrings []string, enums map[string][]string, qms [3][]interface{}, ...) http.Handler
- func NewIntrospectionData(astSchema *ast.Schema) interface{}
- func NilResolverAllowed(on bool) func(*Handler)
- func NoConcurrency(on bool) func(*Handler)
- func NoIntrospection(on bool) func(*Handler)
- func PingFrequency(freq time.Duration) func(*Handler)
- func PongTimeout(timeout time.Duration) func(*Handler)
- type CacheKey
- type Handler
- type ResolverCache
- type ResolverData
- type ResolverLookupTables
Constants ¶
This section is empty.
Variables ¶
var IntroEnums = map[string][]string{
"__TypeKind": {"SCALAR", "OBJECT", "INTERFACE", "UNION", "ENUM", "INPUT_OBJECT", "LIST", "NON_NULL"},
"__DirectiveLocation": {
"QUERY", "MUTATION", "SUBSCRIPTION", "FIELD", "FRAGMENT_DEFINITION", "FRAGMENT_SPREAD", "INLINE_FRAGMENT",
"SCHEMA",
"SCALAR", "OBJECT", "FIELD_DEFINITION", "ARGUMENT_DEFINITION", "INTERFACE", "UNION", "ENUM", "ENUM_VALUE",
"INPUT_OBJECT", "INPUT_FIELD_DEFINITION",
},
}
IntroEnums stores the name and values (text) of the __TypeKind and __DirectiveLocation enums
var IntroEnumsReverse = map[string]map[string]int{
"__TypeKind": {
"SCALAR": 0,
"OBJECT": 1,
"INTERFACE": 2,
"UNION": 3,
"ENUM": 4,
"INPUT_OBJECT": 5,
"LIST": 6,
"NON_NULL": 7,
},
"__DirectiveLocation": {
"QUERY": 0,
"MUTATION": 1,
"SUBSCRIPTION": 2,
"FIELD": 3,
"FRAGMENT_DEFINITION": 4,
"FRAGMENT_SPREAD": 5,
"INLINE_FRAGMENT": 6,
"SCHEMA": 7,
"SCALAR": 8,
"OBJECT": 9,
"FIELD_DEFINITION": 10,
"ARGUMENT_DEFINITION": 11,
"INTERFACE": 12,
"UNION": 13,
"ENUM": 14,
"ENUM_VALUE": 15,
"INPUT_OBJECT": 16,
"INPUT_FIELD_DEFINITION": 17,
},
}
IntroEnumsReverse stores the same enums as IntroEnum, as maps for reverse lookup of int values Each enum is a map keyed by the enum value (string) giving the underlying (int) value
Functions ¶
func FixNumbers ¶ added in v0.2.0
func FixNumbers(val interface{}) interface{}
FixNumbers processes the request variables (decoded from JSON variables map) converting json.Number fields to either floats or ints. It recursively handles JSON lists ([]interface{}) and objects (map[string]interface{}). This assumes that all the JSON numbers were decoded into a json.Number type, rather than int/float, by calling UseNumber() method before Decode() method (of json.Decoder type). TODO: it works but does a lot of memory allocs/copying for slices/maps - need to improve this as it is run on every request
func FuncCache ¶ added in v0.2.0
FuncCache turns on caching forever for the results of function resolvers, but not data (non-func) resolver fields Values are cached indefinitely - but this can be set using the maxAge argument of @cacheControl directive. This setting is overridden if a field uses the @cacheControl directive to enable caching or "no_cache" to disable it.
func InitialTimeout ¶
InitialTimeout sets the length time to wait from when the websocket is opened until the "connection_init" message is received. If the message is not received from the client within the time limit then an error message is returned to the client and the WS is closed.
func New ¶
func New(schemaStrings []string, enums map[string][]string, qms [3][]interface{}, options ...func(*Handler), ) http.Handler
New creates a new handler with the given schema(s) and query/mutation/subscription struct(s) Parameters:
schemaStrings - a slice of strings containing the GraphQL schema(s) - typically only 1
enums - a map of enum names to a slice of strings containing the enum values for all the schemas
can be nil if there are no enums
qms - a slice of query/mutation/subscription structs where:
qms[0] - query struct(s)
qms[1] - mutation struct(s)
qms[2] - subscription struct(s)
options - zero or more options returned by calls to:
handler.FuncCache
handler.NoIntrospection
handler.NoConcurrency
handler.NilResolver
handler.InitialTimeout
handler.PingFrequency
handler.PongTimeout
func NewIntrospectionData ¶
func NilResolverAllowed ¶ added in v0.2.0
NilResolverAllowed allows func resolvers to be nil, whence they return a null value (rather than return an error)
func NoConcurrency ¶ added in v0.2.0
NoConcurrency turns off concurrent execution of queries
func NoIntrospection ¶ added in v0.2.0
NoIntrospection turns off all introspection queries
func PingFrequency ¶
PingFrequency says how often to send a "ping" message (if the client connects with new protocol) or a "ka" (keep alive) message (old protocol)
func PongTimeout ¶
PongTimeout set the length time to wait for a "pong" message from the client after a "ping" message is sent. If the message is not received from the client within the time limit then an error message is returned to the client and the WS is closed. This is *not* used for clients that connect using the old protocol (since "ping" is not sent).
Types ¶
type CacheKey ¶ added in v0.2.0
type CacheKey struct {
// contains filtered or unexported fields
}
CacheKey allows us to uniquely identify a cached value for a resolver Note that the arguments are not enough as we could have two resolvers of the same type that use different data We also need to use the resolver args but can't use a string slice (not comparable - can't be map key), so we convert all the args to strings and put them in a single string separated by a nul byte. TODO check if SHA1, SHA3 or CRC64 of the strings would be better (but ensure args("a","bc") is different to args("ab","c")
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler stores the invariants (schema and structs) used in the GraphQL requests
func (*Handler) ServeHTTP ¶
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServerHTTP receives a GraphQL query as an HTTP request, executes the query (or mutation) and generates an HTTP response or error message
func (*Handler) SetOptions ¶
SetOptions takes a slice of handler options (closures) and executes them
type ResolverCache ¶ added in v0.2.0
type ResolverCache struct {
Mtx *sync.Mutex // protects concurrent access of the following map
Saved map[CacheKey]reflect.Value // cached values of the resolver
}
ResolverCache contains a map (see CacheKey above) and a mutex to protect concurrent access to it
type ResolverData ¶ added in v0.2.0
type ResolverData struct {
Index int // index of the resolver field in the parent struct
// ResolverCache contains cached values of the resolver or is nil if the reeolver does not allow caching
// Note: the map is created (or set to nil) before handling of queries so reading the map itself is safe
// to do concurrently but modifying its contents (adding entries, etc) must be protected with the mutex
Cache ResolverCache // cached values of this resolver
}
ResolverData stores info related to a resolver (field of q query struct)
- index of the resolver field (to avoid a linear search of the fields to find the resolver by name)
- cache of values of the resolver
type ResolverLookupTables ¶ added in v0.2.0
type ResolverLookupTables map[reflect.Type]map[string]ResolverData
ResolverLookupTables - store info on the all resolvers of all query structs The key to the outer map is the type of the struct type containing the resolver The key of the inner map is the name of the resolver (based on the field name or metadata) The info currently has 2 parts
- index of the resolver field within the struct
- a cache of the resolver values returned so far