Spaces:
Sleeping
Sleeping
| // _ _ | |
| // __ _____ __ ___ ___ __ _| |_ ___ | |
| // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ | |
| // \ V V / __/ (_| |\ V /| | (_| | || __/ | |
| // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| | |
| // | |
| // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. | |
| // | |
| // CONTACT: [email protected] | |
| // | |
| // Based on `graphiql.go` from https://github.com/graphql-go/handler | |
| // only made RenderGraphiQL a public function. | |
| package graphiql | |
| import ( | |
| "encoding/json" | |
| "html/template" | |
| "net/http" | |
| "strings" | |
| ) | |
| // graphiqlVersion is the current version of GraphiQL | |
| const graphiqlVersion = "0.11.11" | |
| // graphiqlData is the page data structure of the rendered GraphiQL page | |
| type graphiqlData struct { | |
| GraphiqlVersion string | |
| QueryString string | |
| Variables string | |
| OperationName string | |
| AuthKey string | |
| AuthToken string | |
| } | |
| func AddMiddleware(next http.Handler) http.Handler { | |
| return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
| if strings.HasPrefix(r.URL.Path, "/v1/graphql") && r.Method == http.MethodGet { | |
| renderGraphiQL(w, r) | |
| } else { | |
| next.ServeHTTP(w, r) | |
| } | |
| }) | |
| } | |
| // renderGraphiQL renders the GraphiQL GUI | |
| func renderGraphiQL(w http.ResponseWriter, r *http.Request) { | |
| w.Header().Set("WWW-Authenticate", `Basic realm="Provide your key and token (as username as password respectively)"`) | |
| user, password, authOk := r.BasicAuth() | |
| if !authOk { | |
| http.Error(w, "Not authorized", 401) | |
| return | |
| } | |
| queryParams := r.URL.Query() | |
| t := template.New("GraphiQL") | |
| t, err := t.Parse(graphiqlTemplate) | |
| if err != nil { | |
| http.Error(w, err.Error(), http.StatusInternalServerError) | |
| return | |
| } | |
| // Attempt to deserialize the 'variables' query key to something reasonable. | |
| var queryVars interface{} | |
| err = json.Unmarshal([]byte(queryParams.Get("variables")), &queryVars) | |
| var varsString string | |
| if err == nil { | |
| vars, err := json.MarshalIndent(queryVars, "", " ") | |
| if err != nil { | |
| http.Error(w, err.Error(), http.StatusInternalServerError) | |
| return | |
| } | |
| varsString = string(vars) | |
| if varsString == "null" { | |
| varsString = "" | |
| } | |
| } | |
| // Create result string | |
| d := graphiqlData{ | |
| GraphiqlVersion: graphiqlVersion, | |
| QueryString: queryParams.Get("query"), | |
| Variables: varsString, | |
| OperationName: queryParams.Get("operationName"), | |
| AuthKey: user, | |
| AuthToken: password, | |
| } | |
| err = t.ExecuteTemplate(w, "index", d) | |
| if err != nil { | |
| http.Error(w, err.Error(), http.StatusInternalServerError) | |
| } | |
| } | |
| // tmpl is the page template to render GraphiQL | |
| const graphiqlTemplate = ` | |
| {{ define "index" }} | |
| <!-- | |
| The request to this GraphQL server provided the header "Accept: text/html" | |
| and as a result has been presented GraphiQL - an in-browser IDE for | |
| exploring GraphQL. | |
| If you wish to receive JSON, provide the header "Accept: application/json" or | |
| add "&raw" to the end of the URL within a browser. | |
| --> | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <title>GraphiQL</title> | |
| <meta name="robots" content="noindex" /> | |
| <meta name="referrer" content="origin"> | |
| <style> | |
| body { | |
| height: 100%; | |
| margin: 0; | |
| overflow: hidden; | |
| width: 100%; | |
| } | |
| #graphiql { | |
| height: 100vh; | |
| } | |
| </style> | |
| <link href="//cdn.jsdelivr.net/npm/graphiql@{{ .GraphiqlVersion }}/graphiql.css" rel="stylesheet" /> | |
| <script src="//cdn.jsdelivr.net/es6-promise/4.0.5/es6-promise.auto.min.js"></script> | |
| <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> | |
| </head> | |
| <body> | |
| <div id="graphiql">Loading...</div> | |
| <script> | |
| // Collect the URL parameters | |
| var parameters = {}; | |
| window.location.search.substr(1).split('&').forEach(function (entry) { | |
| var eq = entry.indexOf('='); | |
| if (eq >= 0) { | |
| parameters[decodeURIComponent(entry.slice(0, eq))] = | |
| decodeURIComponent(entry.slice(eq + 1)); | |
| } | |
| }); | |
| // Produce a Location query string from a parameter object. | |
| function locationQuery(params) { | |
| return '?' + Object.keys(params).filter(function (key) { | |
| return Boolean(params[key]); | |
| }).map(function (key) { | |
| return encodeURIComponent(key) + '=' + | |
| encodeURIComponent(params[key]); | |
| }).join('&'); | |
| } | |
| // Derive a fetch URL from the current URL, sans the GraphQL parameters. | |
| var graphqlParamNames = { | |
| query: true, | |
| variables: true, | |
| operationName: true | |
| }; | |
| var otherParams = {}; | |
| for (var k in parameters) { | |
| if (parameters.hasOwnProperty(k) && graphqlParamNames[k] !== true) { | |
| 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', | |
| 'X-API-KEY': {{ .AuthKey }}, | |
| 'X-API-TOKEN': {{ .AuthToken }} | |
| }, | |
| body: JSON.stringify(graphQLParams), | |
| credentials: 'include', | |
| }).then(function (response) { | |
| return response.text(); | |
| }).then(function (responseBody) { | |
| try { | |
| return JSON.parse(responseBody); | |
| } catch (error) { | |
| return responseBody; | |
| } | |
| }); | |
| } | |
| // When the query and variables string is edited, update the URL bar so | |
| // that it can be easily shared. | |
| function onEditQuery(newQuery) { | |
| parameters.query = newQuery; | |
| updateURL(); | |
| } | |
| function onEditVariables(newVariables) { | |
| parameters.variables = newVariables; | |
| updateURL(); | |
| } | |
| function onEditOperationName(newOperationName) { | |
| parameters.operationName = newOperationName; | |
| updateURL(); | |
| } | |
| function updateURL() { | |
| history.replaceState(null, null, locationQuery(parameters)); | |
| } | |
| // Render <GraphiQL /> into the body. | |
| ReactDOM.render( | |
| React.createElement(GraphiQL, { | |
| fetcher: graphQLFetcher, | |
| onEditQuery: onEditQuery, | |
| onEditVariables: onEditVariables, | |
| onEditOperationName: onEditOperationName, | |
| query: {{ .QueryString }}, | |
| response: null, | |
| variables: {{ .Variables }}, | |
| operationName: {{ .OperationName }}, | |
| }), | |
| document.getElementById('graphiql') | |
| ); | |
| </script> | |
| </body> | |
| </html> | |
| {{ end }} | |
| ` | |