aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/graphql-go/handler
diff options
context:
space:
mode:
authorMichael Muré <batolettre@gmail.com>2018-07-19 14:15:50 +0200
committerMichael Muré <batolettre@gmail.com>2018-07-19 14:15:50 +0200
commita2a50f3de0c428c5a61e6a449191be3c4ded86ac (patch)
tree5ecf4f5f1f26933b42a606b741963fa5f66c85aa /vendor/github.com/graphql-go/handler
parent25fb88d7497b00bbe3dda540efde22ffd3de6e49 (diff)
downloadgit-bug-a2a50f3de0c428c5a61e6a449191be3c4ded86ac.tar.gz
webui: add a primitive graphql handler
Diffstat (limited to 'vendor/github.com/graphql-go/handler')
-rw-r--r--vendor/github.com/graphql-go/handler/.gitignore25
-rw-r--r--vendor/github.com/graphql-go/handler/.travis.yml12
-rw-r--r--vendor/github.com/graphql-go/handler/LICENSE22
-rw-r--r--vendor/github.com/graphql-go/handler/README.md79
-rw-r--r--vendor/github.com/graphql-go/handler/graphiql.go199
-rw-r--r--vendor/github.com/graphql-go/handler/handler.go189
6 files changed, 526 insertions, 0 deletions
diff --git a/vendor/github.com/graphql-go/handler/.gitignore b/vendor/github.com/graphql-go/handler/.gitignore
new file mode 100644
index 00000000..3a709f36
--- /dev/null
+++ b/vendor/github.com/graphql-go/handler/.gitignore
@@ -0,0 +1,25 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe
+*.test
+*.prof
+*.swp
diff --git a/vendor/github.com/graphql-go/handler/.travis.yml b/vendor/github.com/graphql-go/handler/.travis.yml
new file mode 100644
index 00000000..3fee687b
--- /dev/null
+++ b/vendor/github.com/graphql-go/handler/.travis.yml
@@ -0,0 +1,12 @@
+language: go
+
+go:
+ - 1.x
+ - tip
+
+before_install:
+ - go get github.com/axw/gocov/gocov
+ - go get github.com/mattn/goveralls
+
+script:
+ - $HOME/gopath/bin/goveralls -service=travis-ci
diff --git a/vendor/github.com/graphql-go/handler/LICENSE b/vendor/github.com/graphql-go/handler/LICENSE
new file mode 100644
index 00000000..4bcca848
--- /dev/null
+++ b/vendor/github.com/graphql-go/handler/LICENSE
@@ -0,0 +1,22 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Hafiz Ismail
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
diff --git a/vendor/github.com/graphql-go/handler/README.md b/vendor/github.com/graphql-go/handler/README.md
new file mode 100644
index 00000000..a6986c5e
--- /dev/null
+++ b/vendor/github.com/graphql-go/handler/README.md
@@ -0,0 +1,79 @@
+# graphql-go-handler [![Build Status](https://travis-ci.org/graphql-go/handler.svg)](https://travis-ci.org/graphql-go/handler) [![GoDoc](https://godoc.org/graphql-go/handler?status.svg)](https://godoc.org/github.com/graphql-go/handler) [![Coverage Status](https://coveralls.io/repos/graphql-go/handler/badge.svg?branch=master&service=github)](https://coveralls.io/github/graphql-go/handler?branch=master) [![Join the chat at https://gitter.im/graphql-go/graphql](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/graphql-go/graphql?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+Golang HTTP.Handler for [graphl-go](https://github.com/graphql-go/graphql)
+
+### Notes:
+This is based on alpha version of `graphql-go` and `graphql-relay-go`.
+Be sure to watch both repositories for latest changes.
+
+### Usage
+
+```go
+package main
+
+import (
+ "net/http"
+ "github.com/graphql-go/handler"
+)
+
+func main() {
+
+ // define GraphQL schema using relay library helpers
+ schema := graphql.NewSchema(...)
+
+ h := handler.New(&handler.Config{
+ Schema: &schema,
+ Pretty: true,
+ GraphiQL: true,
+ })
+
+ // serve HTTP
+ http.Handle("/graphql", h)
+ http.ListenAndServe(":8080", nil)
+}
+```
+
+### Details
+
+The handler will accept requests with
+the parameters:
+
+ * **`query`**: A string GraphQL document to be executed.
+
+ * **`variables`**: The runtime values to use for any GraphQL query variables
+ as a JSON object.
+
+ * **`operationName`**: If the provided `query` contains multiple named
+ operations, this specifies which operation should be executed. If not
+ provided, an 400 error will be returned if the `query` contains multiple
+ named operations.
+
+GraphQL will first look for each parameter in the URL's query-string:
+
+```
+/graphql?query=query+getUser($id:ID){user(id:$id){name}}&variables={"id":"4"}
+```
+
+If not found in the query-string, it will look in the POST request body.
+The `handler` will interpret it
+depending on the provided `Content-Type` header.
+
+ * **`application/json`**: the POST body will be parsed as a JSON
+ object of parameters.
+
+ * **`application/x-www-form-urlencoded`**: this POST body will be
+ parsed as a url-encoded string of key-value pairs.
+
+ * **`application/graphql`**: The POST body will be parsed as GraphQL
+ query string, which provides the `query` parameter.
+
+
+### Examples
+- [golang-graphql-playground](https://github.com/graphql-go/playground)
+- [golang-relay-starter-kit](https://github.com/sogko/golang-relay-starter-kit)
+- [todomvc-relay-go](https://github.com/sogko/todomvc-relay-go)
+
+### Test
+```bash
+$ go get github.com/graphql-go/handler
+$ go build && go test ./...
diff --git a/vendor/github.com/graphql-go/handler/graphiql.go b/vendor/github.com/graphql-go/handler/graphiql.go
new file mode 100644
index 00000000..ace949b4
--- /dev/null
+++ b/vendor/github.com/graphql-go/handler/graphiql.go
@@ -0,0 +1,199 @@
+package handler
+
+import (
+ "encoding/json"
+ "html/template"
+ "net/http"
+
+ "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
+}
+
+// renderGraphiQL renders the GraphiQL GUI
+func renderGraphiQL(w http.ResponseWriter, params graphql.Params) {
+ t := template.New("GraphiQL")
+ t, err := t.Parse(graphiqlTemplate)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+
+ // Create variables string
+ vars, err := json.MarshalIndent(params.VariableValues, "", " ")
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ varsString := string(vars)
+ if varsString == "null" {
+ varsString = ""
+ }
+
+ // Create result string
+ var resString string
+ if params.RequestString == "" {
+ resString = ""
+ } else {
+ result, err := json.MarshalIndent(graphql.Do(params), "", " ")
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ resString = string(result)
+ }
+
+ p := graphiqlPage{
+ GraphiqlVersion: graphiqlVersion,
+ QueryString: params.RequestString,
+ ResultString: resString,
+ VariablesString: varsString,
+ OperationName: params.OperationName,
+ }
+
+ err = t.ExecuteTemplate(w, "index", p)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ }
+ return
+}
+
+// graphiqlVersion is the current version of GraphiQL
+const graphiqlVersion = "0.11.3"
+
+// 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" />
+ <style>
+ html, body {
+ height: 100%;
+ margin: 0;
+ overflow: hidden;
+ width: 100%;
+ }
+ </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>
+</head>
+<body>
+ <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'
+ },
+ 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: {{ .ResultString }},
+ variables: {{ .VariablesString }},
+ operationName: {{ .OperationName }},
+ }),
+ document.body
+ );
+ </script>
+</body>
+</html>
+{{ end }}
+`
diff --git a/vendor/github.com/graphql-go/handler/handler.go b/vendor/github.com/graphql-go/handler/handler.go
new file mode 100644
index 00000000..cfcb1ca9
--- /dev/null
+++ b/vendor/github.com/graphql-go/handler/handler.go
@@ -0,0 +1,189 @@
+package handler
+
+import (
+ "encoding/json"
+ "io/ioutil"
+ "net/http"
+ "net/url"
+ "strings"
+
+ "github.com/graphql-go/graphql"
+
+ "context"
+)
+
+const (
+ ContentTypeJSON = "application/json"
+ ContentTypeGraphQL = "application/graphql"
+ ContentTypeFormURLEncoded = "application/x-www-form-urlencoded"
+)
+
+type Handler struct {
+ Schema *graphql.Schema
+ pretty bool
+ graphiql bool
+}
+type RequestOptions struct {
+ Query string `json:"query" url:"query" schema:"query"`
+ Variables map[string]interface{} `json:"variables" url:"variables" schema:"variables"`
+ OperationName string `json:"operationName" url:"operationName" schema:"operationName"`
+}
+
+// a workaround for getting`variables` as a JSON string
+type requestOptionsCompatibility struct {
+ Query string `json:"query" url:"query" schema:"query"`
+ Variables string `json:"variables" url:"variables" schema:"variables"`
+ OperationName string `json:"operationName" url:"operationName" schema:"operationName"`
+}
+
+func getFromForm(values url.Values) *RequestOptions {
+ query := values.Get("query")
+ if query != "" {
+ // get variables map
+ variables := make(map[string]interface{}, len(values))
+ variablesStr := values.Get("variables")
+ json.Unmarshal([]byte(variablesStr), &variables)
+
+ return &RequestOptions{
+ Query: query,
+ Variables: variables,
+ OperationName: values.Get("operationName"),
+ }
+ }
+
+ return nil
+}
+
+// RequestOptions Parses a http.Request into GraphQL request options struct
+func NewRequestOptions(r *http.Request) *RequestOptions {
+ if reqOpt := getFromForm(r.URL.Query()); reqOpt != nil {
+ return reqOpt
+ }
+
+ if r.Method != "POST" {
+ return &RequestOptions{}
+ }
+
+ if r.Body == nil {
+ return &RequestOptions{}
+ }
+
+ // TODO: improve Content-Type handling
+ contentTypeStr := r.Header.Get("Content-Type")
+ contentTypeTokens := strings.Split(contentTypeStr, ";")
+ contentType := contentTypeTokens[0]
+
+ switch contentType {
+ case ContentTypeGraphQL:
+ body, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ return &RequestOptions{}
+ }
+ return &RequestOptions{
+ Query: string(body),
+ }
+ case ContentTypeFormURLEncoded:
+ if err := r.ParseForm(); err != nil {
+ return &RequestOptions{}
+ }
+
+ if reqOpt := getFromForm(r.PostForm); reqOpt != nil {
+ return reqOpt
+ }
+
+ return &RequestOptions{}
+
+ case ContentTypeJSON:
+ fallthrough
+ default:
+ var opts RequestOptions
+ body, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ return &opts
+ }
+ err = json.Unmarshal(body, &opts)
+ if err != nil {
+ // Probably `variables` was sent as a string instead of an object.
+ // So, we try to be polite and try to parse that as a JSON string
+ var optsCompatible requestOptionsCompatibility
+ json.Unmarshal(body, &optsCompatible)
+ json.Unmarshal([]byte(optsCompatible.Variables), &opts.Variables)
+ }
+ return &opts
+ }
+}
+
+// ContextHandler provides an entrypoint into executing graphQL queries with a
+// user-provided context.
+func (h *Handler) ContextHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
+ // get query
+ opts := NewRequestOptions(r)
+
+ // execute graphql query
+ params := graphql.Params{
+ Schema: *h.Schema,
+ RequestString: opts.Query,
+ VariableValues: opts.Variables,
+ OperationName: opts.OperationName,
+ Context: ctx,
+ }
+ result := graphql.Do(params)
+
+ if h.graphiql {
+ 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)
+ return
+ }
+ }
+
+ // use proper JSON Header
+ w.Header().Add("Content-Type", "application/json; charset=utf-8")
+
+ if h.pretty {
+ w.WriteHeader(http.StatusOK)
+ buff, _ := json.MarshalIndent(result, "", "\t")
+
+ w.Write(buff)
+ } else {
+ w.WriteHeader(http.StatusOK)
+ buff, _ := json.Marshal(result)
+
+ w.Write(buff)
+ }
+}
+
+// ServeHTTP provides an entrypoint into executing graphQL queries.
+func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ h.ContextHandler(r.Context(), w, r)
+}
+
+type Config struct {
+ Schema *graphql.Schema
+ Pretty bool
+ GraphiQL bool
+}
+
+func NewConfig() *Config {
+ return &Config{
+ Schema: nil,
+ Pretty: true,
+ GraphiQL: true,
+ }
+}
+
+func New(p *Config) *Handler {
+ if p == nil {
+ p = NewConfig()
+ }
+ if p.Schema == nil {
+ panic("undefined GraphQL schema")
+ }
+
+ return &Handler{
+ Schema: p.Schema,
+ pretty: p.Pretty,
+ graphiql: p.GraphiQL,
+ }
+}