...

Source file src/github.com/99designs/gqlgen/graphql/playground/playground.go

Documentation: github.com/99designs/gqlgen/graphql/playground

     1  package playground
     2  
     3  import (
     4  	"html/template"
     5  	"net/http"
     6  	"net/url"
     7  )
     8  
     9  var page = template.Must(template.New("graphiql").Parse(`<!DOCTYPE html>
    10  <html>
    11    <head>
    12    	<meta charset="utf-8">
    13    	<title>{{.title}}</title>
    14  	<style>
    15  		body {
    16  			height: 100%;
    17  			margin: 0;
    18  			width: 100%;
    19  			overflow: hidden;
    20  		}
    21  
    22  		#graphiql {
    23  			height: 100vh;
    24  		}
    25  	</style>
    26  	<script
    27  		src="https://cdn.jsdelivr.net/npm/react@18.2.0/umd/react.production.min.js"
    28  		integrity="{{.reactSRI}}"
    29  		crossorigin="anonymous"
    30  	></script>
    31  	<script
    32  		src="https://cdn.jsdelivr.net/npm/react-dom@18.2.0/umd/react-dom.production.min.js"
    33  		integrity="{{.reactDOMSRI}}"
    34  		crossorigin="anonymous"
    35  	></script>
    36      <link
    37  		rel="stylesheet"
    38  		href="https://cdn.jsdelivr.net/npm/graphiql@{{.version}}/graphiql.min.css"
    39  		integrity="{{.cssSRI}}"
    40  		crossorigin="anonymous"
    41  	/>
    42    </head>
    43    <body>
    44      <div id="graphiql">Loading...</div>
    45  
    46  	<script
    47  		src="https://cdn.jsdelivr.net/npm/graphiql@{{.version}}/graphiql.min.js"
    48  		integrity="{{.jsSRI}}"
    49  		crossorigin="anonymous"
    50  	></script>
    51  
    52      <script>
    53  {{- if .endpointIsAbsolute}}
    54        const url = {{.endpoint}};
    55        const subscriptionUrl = {{.subscriptionEndpoint}};
    56  {{- else}}
    57        const url = location.protocol + '//' + location.host + {{.endpoint}};
    58        const wsProto = location.protocol == 'https:' ? 'wss:' : 'ws:';
    59        const subscriptionUrl = wsProto + '//' + location.host + {{.endpoint}};
    60  {{- end}}
    61  {{- if .fetcherHeaders}}
    62        const fetcherHeaders = {{.fetcherHeaders}};
    63  {{- else}}
    64        const fetcherHeaders = undefined;
    65  {{- end}}
    66  {{- if .uiHeaders}}
    67        const uiHeaders = {{.uiHeaders}};
    68  {{- else}}
    69        const uiHeaders = undefined;
    70  {{- end}}
    71  
    72        const fetcher = GraphiQL.createFetcher({ url, subscriptionUrl, headers: fetcherHeaders });
    73        ReactDOM.render(
    74          React.createElement(GraphiQL, {
    75            fetcher: fetcher,
    76            isHeadersEditorEnabled: true,
    77            shouldPersistHeaders: true,
    78  		  headers: JSON.stringify(uiHeaders, null, 2)
    79          }),
    80          document.getElementById('graphiql'),
    81        );
    82      </script>
    83    </body>
    84  </html>
    85  `))
    86  
    87  // Handler responsible for setting up the playground
    88  func Handler(title string, endpoint string) http.HandlerFunc {
    89  	return HandlerWithHeaders(title, endpoint, nil, nil)
    90  }
    91  
    92  // HandlerWithHeaders sets up the playground.
    93  // fetcherHeaders are used by the playground's fetcher instance and will not be visible in the UI.
    94  // uiHeaders are default headers that will show up in the UI headers editor.
    95  func HandlerWithHeaders(title string, endpoint string, fetcherHeaders map[string]string, uiHeaders map[string]string) http.HandlerFunc {
    96  	return func(w http.ResponseWriter, r *http.Request) {
    97  		w.Header().Add("Content-Type", "text/html; charset=UTF-8")
    98  		err := page.Execute(w, map[string]interface{}{
    99  			"title":                title,
   100  			"endpoint":             endpoint,
   101  			"fetcherHeaders":       fetcherHeaders,
   102  			"uiHeaders":            uiHeaders,
   103  			"endpointIsAbsolute":   endpointHasScheme(endpoint),
   104  			"subscriptionEndpoint": getSubscriptionEndpoint(endpoint),
   105  			"version":              "3.0.6",
   106  			"cssSRI":               "sha256-wTzfn13a+pLMB5rMeysPPR1hO7x0SwSeQI+cnw7VdbE=",
   107  			"jsSRI":                "sha256-eNxH+Ah7Z9up9aJYTQycgyNuy953zYZwE9Rqf5rH+r4=",
   108  			"reactSRI":             "sha256-S0lp+k7zWUMk2ixteM6HZvu8L9Eh//OVrt+ZfbCpmgY=",
   109  			"reactDOMSRI":          "sha256-IXWO0ITNDjfnNXIu5POVfqlgYoop36bDzhodR6LW5Pc=",
   110  		})
   111  		if err != nil {
   112  			panic(err)
   113  		}
   114  	}
   115  }
   116  
   117  // endpointHasScheme checks if the endpoint has a scheme.
   118  func endpointHasScheme(endpoint string) bool {
   119  	u, err := url.Parse(endpoint)
   120  	return err == nil && u.Scheme != ""
   121  }
   122  
   123  // getSubscriptionEndpoint returns the subscription endpoint for the given
   124  // endpoint if it is parsable as a URL, or an empty string.
   125  func getSubscriptionEndpoint(endpoint string) string {
   126  	u, err := url.Parse(endpoint)
   127  	if err != nil {
   128  		return ""
   129  	}
   130  
   131  	switch u.Scheme {
   132  	case "https":
   133  		u.Scheme = "wss"
   134  	default:
   135  		u.Scheme = "ws"
   136  	}
   137  
   138  	return u.String()
   139  }
   140  

View as plain text