handler

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 2, 2024 License: MIT Imports: 21 Imported by: 0

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

Constants

This section is empty.

Variables

View Source
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

View Source
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

func FuncCache(on bool) func(*Handler)

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

func InitialTimeout(timeout time.Duration) func(*Handler)

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 NewIntrospectionData(astSchema *ast.Schema) interface{}

func NilResolverAllowed added in v0.2.0

func NilResolverAllowed(on bool) func(*Handler)

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

func NoConcurrency(on bool) func(*Handler)

NoConcurrency turns off concurrent execution of queries

func NoIntrospection added in v0.2.0

func NoIntrospection(on bool) func(*Handler)

NoIntrospection turns off all introspection queries

func PingFrequency

func PingFrequency(freq time.Duration) func(*Handler)

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

func PongTimeout(timeout time.Duration) func(*Handler)

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

func (h *Handler) SetOptions(options ...func(*Handler))

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL