github.com/bewolv/gqlgen@v0.10.12/docs/content/recipes/migration-0.11.md (about)

     1  ---
     2  title: "Migrating to 0.11"
     3  description: Using the new graphql/handler package in gqlgen 0.11 
     4  linkTitle: Migrating to 0.11
     5  menu: { main: { parent: 'recipes' } }
     6  ---
     7  
     8  The handler package has grown organically for a long time, 0.11 is a large cleanup of the handler package to make it 
     9  more modular and easier to maintain once we get to 1.0.
    10   
    11   
    12  ### Transports
    13  
    14  Transports are the first thing that run, they handle decoding the incoming http request, and encoding the graphql 
    15  response. Supported transports are:
    16  
    17   - GET
    18   - JSON POST
    19   - Multipart form
    20   - Websockets
    21  
    22  new usage looks like this
    23  ```go
    24  srv := New(es)
    25  
    26  srv.AddTransport(transport.Websocket{
    27  	KeepAlivePingInterval: 10 * time.Second,
    28  })
    29  srv.AddTransport(transport.Options{})
    30  srv.AddTransport(transport.GET{})
    31  srv.AddTransport(transport.POST{})
    32  srv.AddTransport(transport.MultipartForm{})
    33  ```
    34  
    35  ### New handler extension API
    36  
    37  The core of this changes the handler package to be a set of composable extensions. The extensions implement a set of optional interfaces:
    38  
    39   - **OperationParameterMutator** runs before creating a OperationContext (formerly RequestContext). allows manipulating the raw query before parsing.
    40   - **OperationContextMutator** runs after creating the OperationContext, but before executing the root resolver.
    41   - **OperationInterceptor** runs for each incoming query after parsing and validation, for basic requests the writer will be invoked once, for subscriptions it will be invoked multiple times.
    42   - **ResponseInterceptor** runs around each graphql operation response. This can be called many times for a single operation the case of subscriptions.
    43   - **FieldInterceptor** runs around each field
    44  
    45  ![Anatomy of a request@2x](https://user-images.githubusercontent.com/2247982/68181515-c8a27c00-ffeb-11e9-86f6-1673e7179ecb.png)
    46  
    47  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)`.
    48  
    49  There are a few convenience methods for defining middleware inline, instead of creating an extension
    50  
    51  ```go
    52  srv := handler.New(es)
    53  srv.AroundFields(func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) {
    54  	// this function will be called around every field. next() will evaluate the field and return 
    55  	// its computed value. 
    56  	return next(ctx)
    57  })
    58  srv.AroundOperations(func(ctx context.Context, next graphql.OperationHandler) graphql.ResponseHandler {
    59  	// This function will be called around every operation, next() will return a function that when 
    60  	// called will evaluate one response. Eventually next will return nil, signalling there are no 
    61  	// more results to be returned by the server.
    62  	return next(ctx)
    63  })
    64  srv.AroundResponses(func(ctx context.Context, next graphql.ResponseHandler) *graphql.Response {
    65  	// This function will be called around each response in the operation. next() will evaluate 
    66  	// and return a single response.
    67  	return next(ctx)
    68  })
    69  ```
    70  
    71  
    72  Some of the features supported out of the box by handler extensions:
    73  
    74   - APQ
    75   - Query Complexity
    76   - Error Presenters and Recover Func
    77   - Introspection Query support
    78   - Query AST cache
    79   - Tracing API
    80  
    81  They can be `Use`'d like this:
    82  
    83  ```go
    84  srv := handler.New(es)
    85  srv.Use(extension.Introspection{})
    86  srv.Use(extension.AutomaticPersistedQuery{
    87  	Cache: lru.New(100),
    88  })
    89  srv.Use(apollotracing.Tracer{})
    90  ```
    91  
    92  ### Default server
    93  
    94  We provide a set of default extensions and transports if you aren't ready to customize them yet. Simply:
    95  ```go
    96  handler.NewDefaultServer(es)
    97  ```
    98  
    99  ### More contesistent naming
   100  
   101  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...
   102  
   103  ### Removal of tracing
   104  
   105  Many of the old interfaces collapse down into just a few extension points:
   106  
   107  ![Anatomy of a request@2x (1)](https://user-images.githubusercontent.com/2247982/68181517-cb04d600-ffeb-11e9-9271-0295e6c4ff34.png)
   108  
   109  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. 
   110  
   111  ### Backward compatibility
   112  
   113  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:
   114   
   115   - ResponseMiddleware: The signature used to be `func(ctx context.Context, next func(ctx context.Context) []byte) []byte` and is now `func(ctx context.Context) *Response`. We could maintain BC by marshalling to json before and after, but the change is pretty easy to make and is likely to cause less issues.
   116   - The Tracer interface has been removed, any tracers will need to be reimplemented against the new extension interface.