Background
Go’s “net/http” package provides great out of the box server capabilites with extensible middleware. In order to leverage http middleware in combination with the “github.com/graphql-go/graphql” package, we needed to pass the http.Request.Context() to the graphql handler. Here is how we did so:
Code
1 package main
2
3 import (
4 "encoding/json"
5 "net/http"
6
7 "github.com/graphql-go/graphql"
8 "github.com/graphql-go/handler"
9 "github.com/jinzhu/gorm"
10 _ "github.com/jinzhu/gorm/dialects/postgres"
11 )
12
13 func main () {
14 setupServer ()
15 }
16
17 func setupMux () * http . ServeMux {
18 mux := http . NewServeMux ()
19
20 // graphql Handler
21 graphqlHandler := http . HandlerFunc ( graphqlHandlerFunc )
22
23 // add in addContext middlware
24 mux . Handle ( "/graphql" , addContext ( graphqlHandler ))
25
26 return mux
27 }
28
29 func setupServer () {
30 http . ListenAndServe ( ":8080" , setupMux ())
31 }
32
33 func graphqlHandlerFunc ( w http . ResponseWriter , r * http . Request ) {
34 // get query
35 opts := handler . NewRequestOptions ( r )
36
37 // execute graphql query
38 params := graphql . Params {
39 Schema : Schema , // defined in another file
40 RequestString : opts . Query ,
41 VariableValues : opts . Variables ,
42 OperationName : opts . OperationName ,
43 Context : r . Context (),
44 }
45 result := graphql . Do ( params )
46
47 // output JSON
48 var buff [] byte
49 w . WriteHeader ( http . StatusOK )
50 if prettyPrintGraphQL {
51 buff , _ = json . MarshalIndent ( result , "" , "\t" )
52 } else {
53 buff , _ = json . Marshal ( result )
54 }
55 w . Write ( buff )
56 }
57
58 // Key type is not exported to prevent collisions with context keys defined in
59 // other packages.
60 type key int
61
62 // userAuthKey is the context key for our added struct. Its value of zero is
63 // arbitrary. If this package defined other context keys, they would have
64 // different integer values.
65 const userAuthKey key = 0
66
67 // add values to context
68 func addContext ( next http . Handler ) http . Handler {
69 return http . HandlerFunc ( func ( w http . ResponseWriter , r * http . Request ) {
70 authContext := map [ string ] interface {}{
71 "key1" : 23 ,
72 "key2" : "another value" ,
73 }
74 ctx := context . WithValue ( r . Context (), userAuthKey , authContext )
75 next . ServeHTTP ( w , r . WithContext ( ctx ))
76 })
77 }
Explanation
The AddContext() function is taking the standard http.Request.Context() and supplementing it with our additonal “authContext” map. This Context is then passed to the graphqlHandlerFunc where we setup a new GraphQL instance with the Context initialized to http.Request.Context().
This way, we can access these values within our GraphQL objects.
Tags:
golang
graphql
relay
Boone Putney
Software Development Random Musings Austin, Texas
HumanPlanet
Soleer
Email
LinkedIn
Github
Pass HTTP request Context to GraphQL Handler was published on October 10, 2016 .