Skip to content

Commit

Permalink
Split transports into subpackage
Browse files Browse the repository at this point in the history
  • Loading branch information
vektah committed Oct 28, 2019
1 parent d0f6830 commit b5089ca
Show file tree
Hide file tree
Showing 13 changed files with 82 additions and 51 deletions.
4 changes: 3 additions & 1 deletion graphql/handler/apq.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"crypto/sha256"
"encoding/hex"

"github.com/99designs/gqlgen/graphql/handler/transport"

"github.com/99designs/gqlgen/graphql"
"github.com/mitchellh/mapstructure"
)
Expand All @@ -20,7 +22,7 @@ const (
// see https://github.com/apollographql/apollo-link-persisted-queries
func AutomaticPersistedQuery(cache Cache) Middleware {
return func(next Handler) Handler {
return func(ctx context.Context, writer Writer) {
return func(ctx context.Context, writer transport.Writer) {
rc := graphql.GetRequestContext(ctx)

if rc.Extensions["persistedQuery"] == nil {
Expand Down
6 changes: 4 additions & 2 deletions graphql/handler/complexity.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package handler
import (
"context"

"github.com/99designs/gqlgen/graphql/handler/transport"

"github.com/99designs/gqlgen/graphql"
)

Expand All @@ -11,7 +13,7 @@ import (
// If a query is submitted that exceeds the limit, a 422 status code will be returned.
func ComplexityLimit(limit int) Middleware {
return func(next Handler) Handler {
return func(ctx context.Context, writer Writer) {
return func(ctx context.Context, writer transport.Writer) {
graphql.GetRequestContext(ctx).ComplexityLimit = limit
next(ctx, writer)
}
Expand All @@ -25,7 +27,7 @@ func ComplexityLimit(limit int) Middleware {
// If a query is submitted that exceeds the limit, a 422 status code will be returned.
func ComplexityLimitFunc(f graphql.ComplexityLimitFunc) Middleware {
return func(next Handler) Handler {
return func(ctx context.Context, writer Writer) {
return func(ctx context.Context, writer transport.Writer) {
graphql.GetRequestContext(ctx).ComplexityLimit = f(ctx)
next(ctx, writer)
}
Expand Down
6 changes: 4 additions & 2 deletions graphql/handler/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package handler
import (
"context"

"github.com/99designs/gqlgen/graphql/handler/transport"

"github.com/99designs/gqlgen/graphql"
)

Expand All @@ -11,7 +13,7 @@ import (
// implementation in graphql.DefaultErrorPresenter for an example.
func ErrorPresenter(ep graphql.ErrorPresenterFunc) Middleware {
return func(next Handler) Handler {
return func(ctx context.Context, writer Writer) {
return func(ctx context.Context, writer transport.Writer) {
graphql.GetRequestContext(ctx).ErrorPresenter = ep
next(ctx, writer)
}
Expand All @@ -22,7 +24,7 @@ func ErrorPresenter(ep graphql.ErrorPresenterFunc) Middleware {
// and hide internal error types from clients.
func RecoverFunc(recover graphql.RecoverFunc) Middleware {
return func(next Handler) Handler {
return func(ctx context.Context, writer Writer) {
return func(ctx context.Context, writer transport.Writer) {
graphql.GetRequestContext(ctx).Recover = recover
next(ctx, writer)
}
Expand Down
4 changes: 3 additions & 1 deletion graphql/handler/introspection.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ package handler
import (
"context"

"github.com/99designs/gqlgen/graphql/handler/transport"

"github.com/99designs/gqlgen/graphql"
)

// Introspection enables clients to reflect all of the types available on the graph.
func Introspection() Middleware {
return func(next Handler) Handler {
return func(ctx context.Context, writer Writer) {
return func(ctx context.Context, writer transport.Writer) {
graphql.GetRequestContext(ctx).DisableIntrospection = false
next(ctx, writer)
}
Expand Down
31 changes: 7 additions & 24 deletions graphql/handler/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"fmt"
"net/http"

"github.com/99designs/gqlgen/graphql/handler/transport"

"github.com/vektah/gqlparser/validator"

"github.com/99designs/gqlgen/graphql"
Expand All @@ -17,39 +19,20 @@ import (
type (
Server struct {
es graphql.ExecutableSchema
transports []Transport
transports []transport.Transport
middlewares []Middleware
}

Handler func(ctx context.Context, writer Writer)

Writer func(*graphql.Response)
Handler func(ctx context.Context, writer transport.Writer)

Middleware func(next Handler) Handler

Transport interface {
Supports(r *http.Request) bool
Do(w http.ResponseWriter, r *http.Request) (*graphql.RequestContext, Writer)
}

Option func(Server)

ResponseStream func() *graphql.Response
)

func (w Writer) Errorf(format string, args ...interface{}) {
w(&graphql.Response{
Errors: gqlerror.List{{Message: fmt.Sprintf(format, args...)}},
})
}

func (w Writer) Error(msg string) {
w(&graphql.Response{
Errors: gqlerror.List{{Message: msg}},
})
}

func (s *Server) AddTransport(transport Transport) {
func (s *Server) AddTransport(transport transport.Transport) {
s.transports = append(s.transports, transport)
}

Expand All @@ -63,7 +46,7 @@ func New(es graphql.ExecutableSchema) *Server {
}
}

func (s *Server) getTransport(r *http.Request) Transport {
func (s *Server) getTransport(r *http.Request) transport.Transport {
for _, t := range s.transports {
if t.Supports(r) {
return t
Expand Down Expand Up @@ -96,7 +79,7 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {

// executableSchemaHandler is the inner most handler, it invokes the graph directly after all middleware
// and sends responses to the transport so it can be returned to the client
func (s *Server) executableSchemaHandler(ctx context.Context, write Writer) {
func (s *Server) executableSchemaHandler(ctx context.Context, write transport.Writer) {
rc := graphql.GetRequestContext(ctx)

var gerr *gqlerror.Error
Expand Down
12 changes: 8 additions & 4 deletions graphql/handler/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"testing"

"github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/graphql/handler/transport"
"github.com/stretchr/testify/assert"
"github.com/vektah/gqlparser/ast"
)
Expand All @@ -31,11 +32,14 @@ func TestServer(t *testing.T) {
return &graphql.Response{Data: []byte(`"subscription resp"`)}
}
},
SchemaFunc: func() *ast.Schema {
return &ast.Schema{}
},
}
srv := New(es)
srv.AddTransport(&HTTPGet{})
srv.AddTransport(&transport.HTTPGet{})
srv.Use(func(next Handler) Handler {
return func(ctx context.Context, writer Writer) {
return func(ctx context.Context, writer transport.Writer) {
next(ctx, writer)
}
})
Expand Down Expand Up @@ -67,13 +71,13 @@ func TestServer(t *testing.T) {
t.Run("invokes middleware in order", func(t *testing.T) {
var calls []string
srv.Use(func(next Handler) Handler {
return func(ctx context.Context, writer Writer) {
return func(ctx context.Context, writer transport.Writer) {
calls = append(calls, "first")
next(ctx, writer)
}
})
srv.Use(func(next Handler) Handler {
return func(ctx context.Context, writer Writer) {
return func(ctx context.Context, writer transport.Writer) {
calls = append(calls, "second")
next(ctx, writer)
}
Expand Down
4 changes: 3 additions & 1 deletion graphql/handler/tracer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ package handler
import (
"context"

"github.com/99designs/gqlgen/graphql/handler/transport"

"github.com/99designs/gqlgen/graphql"
)

// Tracer allows you to add a request/resolver tracer that will be called around the root request,
// calling resolver. This is useful for tracing
func Tracer(tracer graphql.Tracer) Middleware {
return func(next Handler) Handler {
return func(ctx context.Context, writer Writer) {
return func(ctx context.Context, writer transport.Writer) {
rc := graphql.GetRequestContext(ctx)
rc.AddTracer(tracer)
rc.AddRequestMiddleware(func(ctx context.Context, next func(ctx context.Context) []byte) []byte {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package handler
package transport

import (
"encoding/json"
Expand All @@ -24,16 +24,24 @@ func (H HTTPGet) Do(w http.ResponseWriter, r *http.Request) (*graphql.RequestCon
reqParams.RawQuery = r.URL.Query().Get("query")
reqParams.OperationName = r.URL.Query().Get("operationName")

writer := Writer(func(response *graphql.Response) {
b, err := json.Marshal(response)
if err != nil {
panic(err)
}
w.Write(b)
})

if variables := r.URL.Query().Get("variables"); variables != "" {
if err := jsonDecode(strings.NewReader(variables), &reqParams.Variables); err != nil {
sendErrorf(w, http.StatusBadRequest, "variables could not be decoded")
writer.Errorf("variables could not be decoded")
return nil, nil
}
}

if extensions := r.URL.Query().Get("extensions"); extensions != "" {
if err := jsonDecode(strings.NewReader(extensions), &reqParams.Extensions); err != nil {
sendErrorf(w, http.StatusBadRequest, "extensions could not be decoded")
writer.Errorf("extensions could not be decoded")
return nil, nil
}
}
Expand All @@ -43,13 +51,7 @@ func (H HTTPGet) Do(w http.ResponseWriter, r *http.Request) (*graphql.RequestCon
// return ctx, nil, nil, gqlerror.List{gqlerror.Errorf("GET requests only allow query operations")}
//}

return reqParams, func(response *graphql.Response) {
b, err := json.Marshal(response)
if err != nil {
panic(err)
}
w.Write(b)
}
return reqParams, writer
}

func jsonDecode(r io.Reader, val interface{}) error {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package handler
package transport

import (
"encoding/json"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package handler
package transport_test

import (
"context"
Expand All @@ -9,6 +9,8 @@ import (
"testing"

"github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/graphql/handler"
"github.com/99designs/gqlgen/graphql/handler/transport"
"github.com/stretchr/testify/assert"
"github.com/vektah/gqlparser"
"github.com/vektah/gqlparser/ast"
Expand All @@ -33,8 +35,8 @@ func TestJsonPost(t *testing.T) {
`})
},
}
h := New(es)
h.AddTransport(JsonPostTransport{})
h := handler.New(es)
h.AddTransport(transport.JsonPostTransport{})

t.Run("success", func(t *testing.T) {
resp := doRequest(h, "POST", "/graphql", `{"query":"{ me { name } }"}`)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package handler
package transport

import "github.com/99designs/gqlgen/graphql"

Expand Down
29 changes: 29 additions & 0 deletions graphql/handler/transport/transport.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package transport

import (
"fmt"
"net/http"

"github.com/99designs/gqlgen/graphql"
"github.com/vektah/gqlparser/gqlerror"
)

type (
Transport interface {
Supports(r *http.Request) bool
Do(w http.ResponseWriter, r *http.Request) (*graphql.RequestContext, Writer)
}
Writer func(*graphql.Response)
)

func (w Writer) Errorf(format string, args ...interface{}) {
w(&graphql.Response{
Errors: gqlerror.List{{Message: fmt.Sprintf(format, args...)}},
})
}

func (w Writer) Error(msg string) {
w(&graphql.Response{
Errors: gqlerror.List{{Message: msg}},
})
}
3 changes: 2 additions & 1 deletion graphql/handler/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"

"github.com/99designs/gqlgen/graphql"
"github.com/99designs/gqlgen/graphql/handler/transport"
)

type middlewareContext struct {
Expand All @@ -19,7 +20,7 @@ func testMiddleware(m Middleware, initialContexts ...graphql.RequestContext) mid
initial = &initialContexts[0]
}

m(func(ctx context.Context, writer Writer) {
m(func(ctx context.Context, writer transport.Writer) {
c.ResultContext = *graphql.GetRequestContext(ctx)
c.InvokedNext = true
})(graphql.WithRequestContext(context.Background(), initial), func(response *graphql.Response) {
Expand Down

0 comments on commit b5089ca

Please sign in to comment.