v0.17.8
v0.17.8 v0.17.27 v0.17.26 v0.17.25 v0.17.24 v0.17.23 v0.17.22 v0.17.21 v0.17.20 v0.17.19 v0.17.18 v0.17.17 v0.17.16 v0.17.15 v0.17.14 v0.17.13 v0.17.12 v0.17.11 v0.17.10 v0.17.9 master

Migrating to 0.11

Migrating to 0.11
[edit]
You are looking at the docs for an older version (v0.17.8). The latest version is v0.17.27.

Updated gqlparser

gqlparser had a breaking change, if you have any references to it in your project your going to need to update them from github.com/vektah/gqlparser to github.com/vektah/gqlparser/v2.

sed -i 's/github.com\/vektah\/gqlparser/github.com\/vektah\/gqlparser\/v2/' $(find -name '*.go')

Handler Refactor

The handler package has grown organically for a long time, 0.11 is a large cleanup of the handler package to make it more modular and easier to maintain once we get to 1.0.

Transports

Transports are the first thing that run, they handle decoding the incoming http request, and encoding the graphql response. Supported transports are:

new usage looks like this

srv := New(es)

srv.AddTransport(transport.Websocket{
	KeepAlivePingInterval: 10 * time.Second,
})
srv.AddTransport(transport.Options{})
srv.AddTransport(transport.GET{})
srv.AddTransport(transport.POST{})
srv.AddTransport(transport.MultipartForm{})

New handler extension API

The core of this changes the handler package to be a set of composable extensions. The extensions implement a set of optional interfaces:

Anatomy of a request@2x

Users of an extension should not need to know which extension points are being used by a given extension, they are added to the server simply by calling Use(extension).

There are a few convenience methods for defining middleware inline, instead of creating an extension

srv := handler.New(es)
srv.AroundFields(func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) {
	// this function will be called around every field. next() will evaluate the field and return
	// its computed value.
	return next(ctx)
})
srv.AroundOperations(func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler {
	// This function will be called around every operation, next() will return a function that when
	// called will evaluate one response. Eventually next will return nil, signalling there are no
	// more results to be returned by the server.
	return next(ctx)
})
srv.AroundResponses(func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response {
	// This function will be called around each response in the operation. next() will evaluate
	// and return a single response.
	return next(ctx)
})

Some of the features supported out of the box by handler extensions:

They can be Use’d like this:

srv := handler.New(es)
srv.Use(extension.Introspection{})
srv.Use(extension.AutomaticPersistedQuery{
	Cache: lru.New(100),
})
srv.Use(apollotracing.Tracer{})

Default server

We provide a set of default extensions and transports if you aren’t ready to customize them yet. Simply:

handler.NewDefaultServer(es)

More consistent naming

As part of cleaning up the names the RequestContext has been renamed to OperationContext, as there can be multiple created during the lifecycle of a request. A new ResponseContext has also been created and error handling has been moved here. This allows each response in a subscription to have its own errors. I’m not sure what bugs this might have been causing before…

Removal of tracing

Many of the old interfaces collapse down into just a few extension points:

Anatomy of a request

The tracing interface has also been removed, tracing stats are now measured in core (eg time to parse query) and made available on the operation/response contexts. Much of the old interface was designed so that users of a tracer dont need to know which extension points it was listening to, the new handler extensions have the same goal.

Backward compatibility

There is a backwards compatibility layer that keeps most of the original interface in place. There are a few places where BC is known to be broken:

New resolver layout

0.11 also added a new way to generate and layout resolvers on disk. We used to only generate resolver implementations whenever the file didnt exist. This behaviour is still there for those that are already used to it, However there is a new mode you can turn on in config:

resolver:
  layout: follow-schema
  dir: graph

This tells gqlgen to generate resolvers next to the schema file that declared the graphql field, which looks like this:

follow-schema layout