-
Notifications
You must be signed in to change notification settings - Fork 136
Allow custom endpoint URL. #33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 2 commits
593f69e
69f77bc
a83c826
16e9f16
aace1d0
d34f105
9041423
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,21 +4,28 @@ 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 | ||
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 | ||
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 { | ||
|
@@ -50,12 +57,30 @@ func renderGraphiQL(w http.ResponseWriter, params graphql.Params) { | |
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, | ||
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) | ||
|
@@ -68,6 +93,9 @@ func renderGraphiQL(w http.ResponseWriter, params graphql.Params) { | |
// 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" }} | ||
|
@@ -94,10 +122,20 @@ add "&raw" to the end of the URL within a browser. | |
} | ||
</style> | ||
<link href="//cdn.jsdelivr.net/npm/graphiql@{{ .GraphiqlVersion }}/graphiql.css" rel="stylesheet" /> | ||
<script src="//cdn.jsdelivr.net/fetch/0.9.0/fetch.min.js"></script> | ||
<script src="//cdn.jsdelivr.net/react/15.4.2/react.min.js"></script> | ||
<script src="//cdn.jsdelivr.net/react/15.4.2/react-dom.min.js"></script> | ||
<script src="//cdn.jsdelivr.net/npm/graphiql@{{ .GraphiqlVersion }}/graphiql.min.js"></script> | ||
|
||
{{ if .UsingHTTP }} | ||
<script src="//cdn.jsdelivr.net/fetch/2.0.1/fetch.min.js"></script> | ||
{{ end }} | ||
{{ if .UsingWS }} | ||
<script src="//unpkg.com/subscriptions-transport-ws@{{ .SubscriptionTransportVersion }}/browser/client.js"></script> | ||
{{ end }} | ||
{{ if and .UsingWS .UsingHTTP }} | ||
<script src="//unpkg.com/[email protected]/browser/client.js"></script> | ||
{{ end }} | ||
|
||
</head> | ||
<body> | ||
<script> | ||
|
@@ -134,28 +172,49 @@ add "&raw" to the end of the URL within a browser. | |
otherParams[k] = parameters[k]; | ||
} | ||
} | ||
var fetchURL = locationQuery(otherParams); | ||
|
||
// Defines a GraphQL fetcher using the fetch API. | ||
function graphQLFetcher(graphQLParams) { | ||
return fetch(fetchURL, { | ||
method: 'post', | ||
headers: { | ||
'Accept': 'application/json', | ||
'Content-Type': 'application/json' | ||
}, | ||
body: JSON.stringify(graphQLParams), | ||
credentials: 'include', | ||
}).then(function (response) { | ||
return response.text(); | ||
}).then(function (responseBody) { | ||
try { | ||
return JSON.parse(responseBody); | ||
} catch (error) { | ||
return responseBody; | ||
} | ||
|
||
{{ if .UsingWS }} | ||
var subscriptionsClient = new window.SubscriptionsTransportWs.SubscriptionClient({{ .EndpointURLWS }}, { | ||
reconnect: true | ||
}); | ||
} | ||
var graphQLWSFetcher = subscriptionsClient.request.bind(subscriptionsClient); | ||
{{ end }} | ||
|
||
{{ if .UsingHTTP }} | ||
var fetchURL = locationQuery(otherParams, {{ .EndpointURL }}); | ||
|
||
// Defines a GraphQL fetcher using the fetch API. | ||
function graphQLHttpFetcher(graphQLParams) { | ||
return fetch(fetchURL, { | ||
method: 'post', | ||
headers: { | ||
'Accept': 'application/json', | ||
'Content-Type': 'application/json' | ||
}, | ||
body: JSON.stringify(graphQLParams), | ||
credentials: 'include', | ||
}).then(function (response) { | ||
return response.text(); | ||
}).then(function (responseBody) { | ||
try { | ||
return JSON.parse(responseBody); | ||
} catch (error) { | ||
return responseBody; | ||
} | ||
}); | ||
} | ||
{{ end }} | ||
|
||
{{ if and .UsingWS .UsingHTTP }} | ||
var fetcher = window.GraphiQLSubscriptionsFetcher.graphQLFetcher(subscriptionsClient, graphQLHttpFetcher); | ||
{{ else }} | ||
{{ if .UsingWS }} | ||
var fetcher = 'graphQLWSFetcher'; | ||
{{ end }} | ||
{{ if .UsingHTTP }} | ||
var fetcher = 'graphQLHttpFetcher'; | ||
{{ end }} | ||
{{ end }} | ||
|
||
// When the query and variables string is edited, update the URL bar so | ||
// that it can be easily shared. | ||
|
@@ -181,7 +240,7 @@ add "&raw" to the end of the URL within a browser. | |
// Render <GraphiQL /> into the body. | ||
ReactDOM.render( | ||
React.createElement(GraphiQL, { | ||
fetcher: graphQLFetcher, | ||
fetcher: fetcher, | ||
onEditQuery: onEditQuery, | ||
onEditVariables: onEditVariables, | ||
onEditOperationName: onEditOperationName, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,9 +19,11 @@ const ( | |
) | ||
|
||
type Handler struct { | ||
Schema *graphql.Schema | ||
pretty bool | ||
graphiql bool | ||
Schema *graphql.Schema | ||
pretty bool | ||
graphiql bool | ||
EndpointURL string | ||
SubscriptionsEndpoint string | ||
} | ||
type RequestOptions struct { | ||
Query string `json:"query" url:"query" schema:"query"` | ||
|
@@ -133,7 +135,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 +162,20 @@ 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 | ||
SubscriptionsEndpoint string | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of making handler.New(&handler.Config{
Schema: ...,
GraphiQL: true,
GraphiQLConfig: &handler.GraphiQLConfig{
Endpoint: ...,
SubscriptionsEndpoint: ...,
}
}) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I noticed that the Apollo server code for GraphiQL mentioned in #31 has a few more configuration variables that might make sense to add here (like additional HTTP headers to be passed to the endpoint for e.g. authentication). |
||
} | ||
|
||
func NewConfig() *Config { | ||
return &Config{ | ||
Schema: nil, | ||
Pretty: true, | ||
GraphiQL: true, | ||
Schema: nil, | ||
Pretty: true, | ||
GraphiQL: true, | ||
EndpointURL: "", | ||
SubscriptionsEndpoint: "", | ||
} | ||
} | ||
|
||
|
@@ -182,8 +188,10 @@ 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, | ||
SubscriptionsEndpoint: p.SubscriptionsEndpoint, | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only
EndpointURLWS
is being used in the template,SubscriptionsEndpoint
isn't. I personally favor the nameSubscriptionsEndpoint
and would passEndpoint
andSubscriptionsEndpoint
(falling back toEndpoint
if not set) in to the template.