Skip to content

Commit

Permalink
Showing 21 changed files with 274 additions and 132 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/internal/tests/testdata/graphql-js
/vendor
/docs/public
/example/chat/node_modules
/example/chat/package-lock.json
2 changes: 1 addition & 1 deletion .gometalinter.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sort": ["path"],
"Deadline": "2m",
"Deadline": "5m",
"Linters": {
"errcheck": {
"Command": "errcheck -abspath -ignore '[rR]ead|[wW]rite|Close'",
4 changes: 2 additions & 2 deletions codegen/templates/data.go

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion codegen/templates/field.gotpl
Original file line number Diff line number Diff line change
@@ -53,7 +53,7 @@
Args: {{if $field.Args }}args{{else}}nil{{end}},
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.{{ $object.GQLType }}_{{ $field.GQLName }}({{ $field.CallArgs }})
})
if err != nil {
44 changes: 26 additions & 18 deletions codegen/templates/generated.gotpl
Original file line number Diff line number Diff line change
@@ -32,12 +32,15 @@ func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *grap
{{- if .QueryRoot }}
ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}

data := ec._{{.QueryRoot.GQLType}}(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
data := ec._{{.QueryRoot.GQLType}}(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
return buf.Bytes()
})

return &graphql.Response{
Data: buf.Bytes(),
Data: buf,
Errors: ec.Errors,
}
{{- else }}
@@ -49,12 +52,15 @@ func (e *executableSchema) Mutation(ctx context.Context, op *query.Operation) *g
{{- if .MutationRoot }}
ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}

data := ec._{{.MutationRoot.GQLType}}(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
data := ec._{{.MutationRoot.GQLType}}(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
return buf.Bytes()
})

return &graphql.Response{
Data: buf.Bytes(),
Data: buf,
Errors: ec.Errors,
}
{{- else }}
@@ -73,18 +79,20 @@ func (e *executableSchema) Subscription(ctx context.Context, op *query.Operation

var buf bytes.Buffer
return func() *graphql.Response {
buf.Reset()
data := next()
if data == nil {
return nil
}
data.MarshalGQL(&buf)
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
buf.Reset()
data := next()

if data == nil {
return nil
}
data.MarshalGQL(&buf)
return buf.Bytes()
})

errs := ec.Errors
ec.Errors = nil
return &graphql.Response{
Data: buf.Bytes(),
Errors: errs,
Data: buf,
Errors: ec.Errors,
}
}
{{- else }}
48 changes: 28 additions & 20 deletions example/chat/generated.go
Original file line number Diff line number Diff line change
@@ -35,25 +35,31 @@ func (e *executableSchema) Schema() *schema.Schema {
func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *graphql.Response {
ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}

data := ec._Query(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
data := ec._Query(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
return buf.Bytes()
})

return &graphql.Response{
Data: buf.Bytes(),
Data: buf,
Errors: ec.Errors,
}
}

func (e *executableSchema) Mutation(ctx context.Context, op *query.Operation) *graphql.Response {
ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}

data := ec._Mutation(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
data := ec._Mutation(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
return buf.Bytes()
})

return &graphql.Response{
Data: buf.Bytes(),
Data: buf,
Errors: ec.Errors,
}
}
@@ -68,18 +74,20 @@ func (e *executableSchema) Subscription(ctx context.Context, op *query.Operation

var buf bytes.Buffer
return func() *graphql.Response {
buf.Reset()
data := next()
if data == nil {
return nil
}
data.MarshalGQL(&buf)
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
buf.Reset()
data := next()

if data == nil {
return nil
}
data.MarshalGQL(&buf)
return buf.Bytes()
})

errs := ec.Errors
ec.Errors = nil
return &graphql.Response{
Data: buf.Bytes(),
Errors: errs,
Data: buf,
Errors: ec.Errors,
}
}
}
@@ -235,7 +243,7 @@ func (ec *executionContext) _Mutation_post(ctx context.Context, field graphql.Co
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Mutation_post(rctx, args["text"].(string), args["username"].(string), args["roomName"].(string))
})
if err != nil {
@@ -300,7 +308,7 @@ func (ec *executionContext) _Query_room(ctx context.Context, field graphql.Colle
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_room(rctx, args["name"].(string))
})
if err != nil {
2 changes: 2 additions & 0 deletions example/chat/package.json
Original file line number Diff line number Diff line change
@@ -5,6 +5,8 @@
"dependencies": {
"apollo-cache-inmemory": "^1.1.9",
"apollo-client": "^2.2.5",
"graphql-tag": "^2.9.1",
"graphql": "^0.13.2",
"react": "^16.2.0",
"react-apollo": "^2.1.0-beta.2",
"react-dom": "^16.2.0",
43 changes: 43 additions & 0 deletions example/chat/server/server.go
Original file line number Diff line number Diff line change
@@ -3,15 +3,26 @@ package main
import (
"log"
"net/http"
"net/url"
"time"

"github.com/gorilla/websocket"
"github.com/opentracing/opentracing-go"
"github.com/vektah/gqlgen/example/chat"
"github.com/vektah/gqlgen/handler"
gqlopentracing "github.com/vektah/gqlgen/opentracing"
"sourcegraph.com/sourcegraph/appdash"
appdashtracer "sourcegraph.com/sourcegraph/appdash/opentracing"
"sourcegraph.com/sourcegraph/appdash/traceapp"
)

func main() {
startAppdashServer()

http.Handle("/", handler.Playground("Todo", "/query"))
http.Handle("/query", handler.GraphQL(chat.MakeExecutableSchema(chat.New()),
handler.ResolverMiddleware(gqlopentracing.ResolverMiddleware()),
handler.RequestMiddleware(gqlopentracing.RequestMiddleware()),
handler.WebsocketUpgrader(websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
@@ -20,3 +31,35 @@ func main() {
)
log.Fatal(http.ListenAndServe(":8085", nil))
}

func startAppdashServer() opentracing.Tracer {
memStore := appdash.NewMemoryStore()
store := &appdash.RecentStore{
MinEvictAge: 5 * time.Minute,
DeleteStore: memStore,
}

url, err := url.Parse("http://localhost:8700")
if err != nil {
log.Fatal(err)
}
tapp, err := traceapp.New(nil, url)
if err != nil {
log.Fatal(err)
}
tapp.Store = store
tapp.Queryer = memStore

go func() {
log.Fatal(http.ListenAndServe(":8700", tapp))
}()
tapp.Store = store
tapp.Queryer = memStore

collector := appdash.NewLocalCollector(store)
tracer := appdashtracer.NewTracer(collector)
opentracing.InitGlobalTracer(tracer)

log.Println("Appdash web UI running on HTTP :8700")
return tracer
}
21 changes: 12 additions & 9 deletions example/dataloader/generated.go
Original file line number Diff line number Diff line change
@@ -38,12 +38,15 @@ func (e *executableSchema) Schema() *schema.Schema {
func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *graphql.Response {
ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}

data := ec._Query(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
data := ec._Query(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
return buf.Bytes()
})

return &graphql.Response{
Data: buf.Bytes(),
Data: buf,
Errors: ec.Errors,
}
}
@@ -155,7 +158,7 @@ func (ec *executionContext) _Customer_address(ctx context.Context, field graphql
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Customer_address(rctx, obj)
})
if err != nil {
@@ -187,7 +190,7 @@ func (ec *executionContext) _Customer_orders(ctx context.Context, field graphql.
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Customer_orders(rctx, obj)
})
if err != nil {
@@ -290,7 +293,7 @@ func (ec *executionContext) _Order_items(ctx context.Context, field graphql.Coll
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Order_items(rctx, obj)
})
if err != nil {
@@ -351,7 +354,7 @@ func (ec *executionContext) _Query_customers(ctx context.Context, field graphql.
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_customers(rctx)
})
if err != nil {
@@ -403,7 +406,7 @@ func (ec *executionContext) _Query_torture(ctx context.Context, field graphql.Co
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_torture(rctx, args["customerIds"].([][]int))
})
if err != nil {
6 changes: 5 additions & 1 deletion example/dataloader/server/server.go
Original file line number Diff line number Diff line change
@@ -25,7 +25,11 @@ func main() {
router.Use(dataloader.LoaderMiddleware)

router.Handle("/", handler.Playground("Dataloader", "/query"))
router.Handle("/query", handler.GraphQL(dataloader.MakeExecutableSchema(&dataloader.Resolver{}), handler.Use(gqlopentracing.Middleware())))
router.Handle("/query", handler.GraphQL(
dataloader.MakeExecutableSchema(&dataloader.Resolver{}),
handler.ResolverMiddleware(gqlopentracing.ResolverMiddleware()),
handler.RequestMiddleware(gqlopentracing.RequestMiddleware()),
))

log.Println("connect to http://localhost:8082/ for graphql playground")
log.Fatal(http.ListenAndServe(":8082", router))
19 changes: 11 additions & 8 deletions example/scalars/generated.go
Original file line number Diff line number Diff line change
@@ -39,12 +39,15 @@ func (e *executableSchema) Schema() *schema.Schema {
func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *graphql.Response {
ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}

data := ec._Query(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
data := ec._Query(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
return buf.Bytes()
})

return &graphql.Response{
Data: buf.Bytes(),
Data: buf,
Errors: ec.Errors,
}
}
@@ -153,7 +156,7 @@ func (ec *executionContext) _Query_user(ctx context.Context, field graphql.Colle
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_user(rctx, args["id"].(external.ObjectID))
})
if err != nil {
@@ -205,7 +208,7 @@ func (ec *executionContext) _Query_search(ctx context.Context, field graphql.Col
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_search(rctx, args["input"].(SearchArgs))
})
if err != nil {
@@ -321,7 +324,7 @@ func (ec *executionContext) _User_primitiveResolver(ctx context.Context, field g
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.User_primitiveResolver(rctx, obj)
})
if err != nil {
@@ -350,7 +353,7 @@ func (ec *executionContext) _User_customResolver(ctx context.Context, field grap
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.User_customResolver(rctx, obj)
})
if err != nil {
13 changes: 8 additions & 5 deletions example/selection/generated.go
Original file line number Diff line number Diff line change
@@ -34,12 +34,15 @@ func (e *executableSchema) Schema() *schema.Schema {
func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *graphql.Response {
ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}

data := ec._Query(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
data := ec._Query(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
return buf.Bytes()
})

return &graphql.Response{
Data: buf.Bytes(),
Data: buf,
Errors: ec.Errors,
}
}
@@ -210,7 +213,7 @@ func (ec *executionContext) _Query_events(ctx context.Context, field graphql.Col
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_events(rctx)
})
if err != nil {
52 changes: 29 additions & 23 deletions example/starwars/generated.go
Original file line number Diff line number Diff line change
@@ -53,25 +53,31 @@ func (e *executableSchema) Schema() *schema.Schema {
func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *graphql.Response {
ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}

data := ec._Query(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
data := ec._Query(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
return buf.Bytes()
})

return &graphql.Response{
Data: buf.Bytes(),
Data: buf,
Errors: ec.Errors,
}
}

func (e *executableSchema) Mutation(ctx context.Context, op *query.Operation) *graphql.Response {
ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}

data := ec._Mutation(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
data := ec._Mutation(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
return buf.Bytes()
})

return &graphql.Response{
Data: buf.Bytes(),
Data: buf,
Errors: ec.Errors,
}
}
@@ -142,7 +148,7 @@ func (ec *executionContext) _Droid_friends(ctx context.Context, field graphql.Co
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Droid_friends(rctx, obj)
})
if err != nil {
@@ -206,7 +212,7 @@ func (ec *executionContext) _Droid_friendsConnection(ctx context.Context, field
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Droid_friendsConnection(rctx, obj, args["first"].(*int), args["after"].(*string))
})
if err != nil {
@@ -282,7 +288,7 @@ func (ec *executionContext) _FriendsConnection_edges(ctx context.Context, field
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.FriendsConnection_edges(rctx, obj)
})
if err != nil {
@@ -315,7 +321,7 @@ func (ec *executionContext) _FriendsConnection_friends(ctx context.Context, fiel
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.FriendsConnection_friends(rctx, obj)
})
if err != nil {
@@ -463,7 +469,7 @@ func (ec *executionContext) _Human_friends(ctx context.Context, field graphql.Co
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Human_friends(rctx, obj)
})
if err != nil {
@@ -527,7 +533,7 @@ func (ec *executionContext) _Human_friendsConnection(ctx context.Context, field
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Human_friendsConnection(rctx, obj, args["first"].(*int), args["after"].(*string))
})
if err != nil {
@@ -565,7 +571,7 @@ func (ec *executionContext) _Human_starships(ctx context.Context, field graphql.
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Human_starships(rctx, obj)
})
if err != nil {
@@ -633,7 +639,7 @@ func (ec *executionContext) _Mutation_createReview(ctx context.Context, field gr
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Mutation_createReview(rctx, args["episode"].(Episode), args["review"].(Review))
})
if err != nil {
@@ -763,7 +769,7 @@ func (ec *executionContext) _Query_hero(ctx context.Context, field graphql.Colle
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_hero(rctx, args["episode"].(Episode))
})
if err != nil {
@@ -818,7 +824,7 @@ func (ec *executionContext) _Query_reviews(ctx context.Context, field graphql.Co
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_reviews(rctx, args["episode"].(Episode), args["since"].(*time.Time))
})
if err != nil {
@@ -862,7 +868,7 @@ func (ec *executionContext) _Query_search(ctx context.Context, field graphql.Col
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_search(rctx, args["text"].(string))
})
if err != nil {
@@ -906,7 +912,7 @@ func (ec *executionContext) _Query_character(ctx context.Context, field graphql.
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_character(rctx, args["id"].(string))
})
if err != nil {
@@ -946,7 +952,7 @@ func (ec *executionContext) _Query_droid(ctx context.Context, field graphql.Coll
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_droid(rctx, args["id"].(string))
})
if err != nil {
@@ -989,7 +995,7 @@ func (ec *executionContext) _Query_human(ctx context.Context, field graphql.Coll
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_human(rctx, args["id"].(string))
})
if err != nil {
@@ -1032,7 +1038,7 @@ func (ec *executionContext) _Query_starship(ctx context.Context, field graphql.C
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_starship(rctx, args["id"].(string))
})
if err != nil {
2 changes: 1 addition & 1 deletion example/starwars/server/server.go
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ import (
func main() {
http.Handle("/", handler.Playground("Starwars", "/query"))
http.Handle("/query", handler.GraphQL(starwars.MakeExecutableSchema(starwars.NewResolver()),
handler.Use(func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) {
handler.ResolverMiddleware(func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) {
rc := graphql.GetResolverContext(ctx)
fmt.Println("Entered", rc.Object, rc.Field.Name)
res, err = next(ctx)
32 changes: 19 additions & 13 deletions example/todo/generated.go
Original file line number Diff line number Diff line change
@@ -37,25 +37,31 @@ func (e *executableSchema) Schema() *schema.Schema {
func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *graphql.Response {
ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}

data := ec._MyQuery(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
data := ec._MyQuery(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
return buf.Bytes()
})

return &graphql.Response{
Data: buf.Bytes(),
Data: buf,
Errors: ec.Errors,
}
}

func (e *executableSchema) Mutation(ctx context.Context, op *query.Operation) *graphql.Response {
ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}

data := ec._MyMutation(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
data := ec._MyMutation(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
return buf.Bytes()
})

return &graphql.Response{
Data: buf.Bytes(),
Data: buf,
Errors: ec.Errors,
}
}
@@ -111,7 +117,7 @@ func (ec *executionContext) _MyMutation_createTodo(ctx context.Context, field gr
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.MyMutation_createTodo(rctx, args["todo"].(TodoInput))
})
if err != nil {
@@ -152,7 +158,7 @@ func (ec *executionContext) _MyMutation_updateTodo(ctx context.Context, field gr
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.MyMutation_updateTodo(rctx, args["id"].(int), args["changes"].(map[string]interface{}))
})
if err != nil {
@@ -224,7 +230,7 @@ func (ec *executionContext) _MyQuery_todo(ctx context.Context, field graphql.Col
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.MyQuery_todo(rctx, args["id"].(int))
})
if err != nil {
@@ -256,7 +262,7 @@ func (ec *executionContext) _MyQuery_lastTodo(ctx context.Context, field graphql
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.MyQuery_lastTodo(rctx)
})
if err != nil {
@@ -288,7 +294,7 @@ func (ec *executionContext) _MyQuery_todos(ctx context.Context, field graphql.Co
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.MyQuery_todos(rctx)
})
if err != nil {
11 changes: 7 additions & 4 deletions graphql/context.go
Original file line number Diff line number Diff line change
@@ -9,14 +9,17 @@ import (

type Resolver func(ctx context.Context) (res interface{}, err error)
type ResolverMiddleware func(ctx context.Context, next Resolver) (res interface{}, err error)
type RequestMiddleware func(ctx context.Context, next func(ctx context.Context) []byte) []byte

type RequestContext struct {
errors.Builder

Variables map[string]interface{}
Doc *query.Document
Recover RecoverFunc
Middleware ResolverMiddleware
RawQuery string
Variables map[string]interface{}
Doc *query.Document
Recover RecoverFunc
ResolverMiddleware ResolverMiddleware
RequestMiddleware RequestMiddleware
}

type key string
41 changes: 36 additions & 5 deletions handler/graphql.go
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@ type Config struct {
recover graphql.RecoverFunc
formatError func(error) string
resolverHook graphql.ResolverMiddleware
requestHook graphql.RequestMiddleware
}

type Option func(cfg *Config)
@@ -47,7 +48,11 @@ func FormatErrorFunc(f func(error) string) Option {
}
}

func Use(middleware graphql.ResolverMiddleware) Option {
// ResolverMiddleware allows you to define a function that will be called around every resolver,
// useful for tracing and logging.
// It will only be called for user defined resolvers, any direct binding to models is assumed
// to cost nothing.
func ResolverMiddleware(middleware graphql.ResolverMiddleware) Option {
return func(cfg *Config) {
if cfg.resolverHook == nil {
cfg.resolverHook = middleware
@@ -63,6 +68,24 @@ func Use(middleware graphql.ResolverMiddleware) Option {
}
}

// RequestMiddleware allows you to define a function that will be called around the root request,
// after the query has been parsed. This is useful for logging and tracing
func RequestMiddleware(middleware graphql.RequestMiddleware) Option {
return func(cfg *Config) {
if cfg.requestHook == nil {
cfg.requestHook = middleware
return
}

lastResolve := cfg.requestHook
cfg.requestHook = func(ctx context.Context, next func(ctx context.Context) []byte) []byte {
return lastResolve(ctx, func(ctx context.Context) []byte {
return middleware(ctx, next)
})
}
}
}

func GraphQL(exec graphql.ExecutableSchema, options ...Option) http.HandlerFunc {
cfg := Config{
recover: graphql.DefaultRecoverFunc,
@@ -82,6 +105,12 @@ func GraphQL(exec graphql.ExecutableSchema, options ...Option) http.HandlerFunc
}
}

if cfg.requestHook == nil {
cfg.requestHook = func(ctx context.Context, next func(ctx context.Context) []byte) []byte {
return next(ctx)
}
}

return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodOptions {
w.Header().Set("Allow", "OPTIONS, GET, POST")
@@ -136,10 +165,12 @@ func GraphQL(exec graphql.ExecutableSchema, options ...Option) http.HandlerFunc
}

ctx := graphql.WithRequestContext(r.Context(), &graphql.RequestContext{
Doc: doc,
Variables: reqParams.Variables,
Recover: cfg.recover,
Middleware: cfg.resolverHook,
Doc: doc,
RawQuery: reqParams.Query,
Variables: reqParams.Variables,
Recover: cfg.recover,
ResolverMiddleware: cfg.resolverHook,
RequestMiddleware: cfg.requestHook,
Builder: errors.Builder{
ErrorMessageFn: cfg.formatError,
},
12 changes: 7 additions & 5 deletions handler/websocket.go
Original file line number Diff line number Diff line change
@@ -49,7 +49,7 @@ func connectWs(exec graphql.ExecutableSchema, w http.ResponseWriter, r *http.Req
"Sec-Websocket-Protocol": []string{"graphql-ws"},
})
if err != nil {
log.Printf("unable to upgrade connection to websocket %s: ", err.Error())
log.Printf("unable to upgrade %T to websocket %s: ", w, err.Error())
sendErrorf(w, http.StatusBadRequest, "unable to upgrade")
return
}
@@ -156,10 +156,12 @@ func (c *wsConnection) subscribe(message *operationMessage) bool {
}

ctx := graphql.WithRequestContext(c.ctx, &graphql.RequestContext{
Doc: doc,
Variables: reqParams.Variables,
Recover: c.cfg.recover,
Middleware: c.cfg.resolverHook,
Doc: doc,
Variables: reqParams.Variables,
RawQuery: reqParams.Query,
Recover: c.cfg.recover,
ResolverMiddleware: c.cfg.resolverHook,
RequestMiddleware: c.cfg.requestHook,
Builder: errors.Builder{
ErrorMessageFn: c.cfg.formatError,
},
18 changes: 15 additions & 3 deletions opentracing/opentracing.go
Original file line number Diff line number Diff line change
@@ -10,16 +10,14 @@ import (
"github.com/vektah/gqlgen/graphql"
)

func Middleware() graphql.ResolverMiddleware {
func ResolverMiddleware() graphql.ResolverMiddleware {
return func(ctx context.Context, next graphql.Resolver) (interface{}, error) {
rctx := graphql.GetResolverContext(ctx)

span, ctx := opentracing.StartSpanFromContext(ctx, rctx.Object+"_"+rctx.Field.Name,
opentracing.Tag{Key: "resolver.object", Value: rctx.Object},
opentracing.Tag{Key: "resolver.field", Value: rctx.Field.Name},
)
defer span.Finish()

ext.SpanKind.Set(span, "server")
ext.Component.Set(span, "gqlgen")

@@ -37,3 +35,17 @@ func Middleware() graphql.ResolverMiddleware {
return res, err
}
}

func RequestMiddleware() graphql.RequestMiddleware {
return func(ctx context.Context, next func(ctx context.Context) []byte) []byte {
requestContext := graphql.GetRequestContext(ctx)
span, ctx := opentracing.StartSpanFromContext(ctx, requestContext.RawQuery)
defer span.Finish()
ext.SpanKind.Set(span, "server")
ext.Component.Set(span, "gqlgen")

res := next(ctx)

return res
}
}
27 changes: 15 additions & 12 deletions test/generated.go
Original file line number Diff line number Diff line change
@@ -44,12 +44,15 @@ func (e *executableSchema) Schema() *schema.Schema {
func (e *executableSchema) Query(ctx context.Context, op *query.Operation) *graphql.Response {
ec := executionContext{graphql.GetRequestContext(ctx), e.resolvers}

data := ec._Query(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
buf := ec.RequestMiddleware(ctx, func(ctx context.Context) []byte {
data := ec._Query(ctx, op.Selections)
var buf bytes.Buffer
data.MarshalGQL(&buf)
return buf.Bytes()
})

return &graphql.Response{
Data: buf.Bytes(),
Data: buf,
Errors: ec.Errors,
}
}
@@ -219,7 +222,7 @@ func (ec *executionContext) _OuterObject_inner(ctx context.Context, field graphq
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.OuterObject_inner(rctx, obj)
})
if err != nil {
@@ -322,7 +325,7 @@ func (ec *executionContext) _Query_nestedInputs(ctx context.Context, field graph
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_nestedInputs(rctx, args["input"].([][]models.OuterInput))
})
if err != nil {
@@ -354,7 +357,7 @@ func (ec *executionContext) _Query_nestedOutputs(ctx context.Context, field grap
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_nestedOutputs(rctx)
})
if err != nil {
@@ -393,7 +396,7 @@ func (ec *executionContext) _Query_shapes(ctx context.Context, field graphql.Col
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_shapes(rctx)
})
if err != nil {
@@ -442,7 +445,7 @@ func (ec *executionContext) _Query_recursive(ctx context.Context, field graphql.
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_recursive(rctx, args["input"].(*RecursiveInputSlice))
})
if err != nil {
@@ -490,7 +493,7 @@ func (ec *executionContext) _Query_mapInput(ctx context.Context, field graphql.C
Args: args,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_mapInput(rctx, args["input"].(*map[string]interface{}))
})
if err != nil {
@@ -522,7 +525,7 @@ func (ec *executionContext) _Query_collision(ctx context.Context, field graphql.
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_collision(rctx)
})
if err != nil {
@@ -554,7 +557,7 @@ func (ec *executionContext) _Query_invalidIdentifier(ctx context.Context, field
Args: nil,
Field: field,
})
resTmp, err := ec.Middleware(rctx, func(rctx context.Context) (interface{}, error) {
resTmp, err := ec.ResolverMiddleware(rctx, func(rctx context.Context) (interface{}, error) {
return ec.resolvers.Query_invalidIdentifier(rctx)
})
if err != nil {
5 changes: 4 additions & 1 deletion test/resolvers_test.go
Original file line number Diff line number Diff line change
@@ -71,7 +71,10 @@ func TestErrorConverter(t *testing.T) {
func mkctx(doc *query.Document, errFn func(e error) string) context.Context {
return graphql.WithRequestContext(context.Background(), &graphql.RequestContext{
Doc: doc,
Middleware: func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) {
ResolverMiddleware: func(ctx context.Context, next graphql.Resolver) (res interface{}, err error) {
return next(ctx)
},
RequestMiddleware: func(ctx context.Context, next func(ctx context.Context) []byte) []byte {
return next(ctx)
},
Builder: gqlerrors.Builder{

0 comments on commit 3ceaa18

Please sign in to comment.