From 593f69e16a26c4e8126b5b88c85821a28569065a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Wed, 3 Jan 2018 13:48:26 +0700 Subject: [PATCH 1/7] Allow custom endpoint URL --- graphiql.go | 6 ++++-- handler.go | 30 +++++++++++++++++------------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/graphiql.go b/graphiql.go index d997374..f30d713 100644 --- a/graphiql.go +++ b/graphiql.go @@ -15,10 +15,11 @@ type graphiqlPage struct { ResultString string VariablesString string OperationName string + EndpointURL template.URL } // renderGraphiQL renders the GraphiQL GUI -func renderGraphiQL(w http.ResponseWriter, params graphql.Params) { +func renderGraphiQL(w http.ResponseWriter, params graphql.Params, handler Handler) { t := template.New("GraphiQL") t, err := t.Parse(graphiqlTemplate) if err != nil { @@ -56,6 +57,7 @@ func renderGraphiQL(w http.ResponseWriter, params graphql.Params) { ResultString: resString, VariablesString: varsString, OperationName: params.OperationName, + EndpointURL: template.URL(handler.EndpointURL), } err = t.ExecuteTemplate(w, "index", p) @@ -134,7 +136,7 @@ add "&raw" to the end of the URL within a browser. otherParams[k] = parameters[k]; } } - var fetchURL = locationQuery(otherParams); + var fetchURL = locationQuery(otherParams, {{ .EndpointURL }}); // Defines a GraphQL fetcher using the fetch API. function graphQLFetcher(graphQLParams) { diff --git a/handler.go b/handler.go index cfcb1ca..7dbd351 100644 --- a/handler.go +++ b/handler.go @@ -19,9 +19,10 @@ const ( ) type Handler struct { - Schema *graphql.Schema - pretty bool - graphiql bool + Schema *graphql.Schema + pretty bool + graphiql bool + EndpointURL string } type RequestOptions struct { Query string `json:"query" url:"query" schema:"query"` @@ -133,7 +134,7 @@ func (h *Handler) ContextHandler(ctx context.Context, w http.ResponseWriter, r * acceptHeader := r.Header.Get("Accept") _, raw := r.URL.Query()["raw"] if !raw && !strings.Contains(acceptHeader, "application/json") && strings.Contains(acceptHeader, "text/html") { - renderGraphiQL(w, params) + renderGraphiQL(w, params, *h) return } } @@ -160,16 +161,18 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { } type Config struct { - Schema *graphql.Schema - Pretty bool - GraphiQL bool + Schema *graphql.Schema + Pretty bool + GraphiQL bool + EndpointURL string } func NewConfig() *Config { return &Config{ - Schema: nil, - Pretty: true, - GraphiQL: true, + Schema: nil, + Pretty: true, + GraphiQL: true, + EndpointURL: "/", } } @@ -182,8 +185,9 @@ func New(p *Config) *Handler { } return &Handler{ - Schema: p.Schema, - pretty: p.Pretty, - graphiql: p.GraphiQL, + Schema: p.Schema, + pretty: p.Pretty, + graphiql: p.GraphiQL, + EndpointURL: p.EndpointURL, } } From 69f77bc6e27e0af28cd49c0c4ae0e69f67589e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Andr=C3=A9=20Santoni?= Date: Wed, 3 Jan 2018 15:30:39 +0700 Subject: [PATCH 2/7] Handle websocket subscriptions in GraphiQL --- graphiql.go | 127 +++++++++++++++++++++++++++++++++++++--------------- handler.go | 36 ++++++++------- 2 files changed, 112 insertions(+), 51 deletions(-) diff --git a/graphiql.go b/graphiql.go index f30d713..cf808ee 100644 --- a/graphiql.go +++ b/graphiql.go @@ -4,18 +4,24 @@ import ( "encoding/json" "html/template" "net/http" + "strings" "github.com/graphql-go/graphql" ) // page is the page data structure of the rendered GraphiQL page type graphiqlPage struct { - GraphiqlVersion string - QueryString string - ResultString string - VariablesString string - OperationName string - EndpointURL template.URL + GraphiqlVersion string + SubscriptionTransportVersion string + QueryString string + ResultString string + VariablesString string + OperationName string + EndpointURL template.URL + EndpointURLWS template.URL + SubscriptionsEndpoint template.URL + UsingHTTP bool + UsingWS bool } // renderGraphiQL renders the GraphiQL GUI @@ -51,13 +57,30 @@ func renderGraphiQL(w http.ResponseWriter, params graphql.Params, handler Handle resString = string(result) } + endpointWS := strings.HasPrefix(handler.EndpointURL, "ws://") + UsingHTTP := !endpointWS + UsingWS := endpointWS || handler.SubscriptionsEndpoint != "" + EndpointURLWS := "" + if UsingWS { + if endpointWS { + EndpointURLWS = handler.EndpointURL + } else { + EndpointURLWS = handler.SubscriptionsEndpoint + } + } + p := graphiqlPage{ - GraphiqlVersion: graphiqlVersion, - QueryString: params.RequestString, - ResultString: resString, - VariablesString: varsString, - OperationName: params.OperationName, - EndpointURL: template.URL(handler.EndpointURL), + GraphiqlVersion: graphiqlVersion, + SubscriptionTransportVersion: subscriptionTransportVersion, + QueryString: params.RequestString, + ResultString: resString, + VariablesString: varsString, + OperationName: params.OperationName, + EndpointURL: template.URL(handler.EndpointURL), + EndpointURLWS: template.URL(EndpointURLWS), + SubscriptionsEndpoint: template.URL(handler.SubscriptionsEndpoint), + UsingHTTP: UsingHTTP, + UsingWS: UsingWS, } err = t.ExecuteTemplate(w, "index", p) @@ -70,6 +93,9 @@ func renderGraphiQL(w http.ResponseWriter, params graphql.Params, handler Handle // graphiqlVersion is the current version of GraphiQL const graphiqlVersion = "0.11.10" +// subscriptionTransportVersion is the current version of the subscription transport of GraphiQL +const subscriptionTransportVersion = "0.8.2" + // tmpl is the page template to render GraphiQL const graphiqlTemplate = ` {{ define "index" }} @@ -96,10 +122,20 @@ add "&raw" to the end of the URL within a browser. } - + + {{ if .UsingHTTP }} + + {{ end }} + {{ if .UsingWS }} + + {{ end }} + {{ if and .UsingWS .UsingHTTP }} + + {{ end }} +