Skip to content
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

Header support in graphiQL interface #80

Open
ShivanshJ opened this issue Jun 27, 2020 · 9 comments
Open

Header support in graphiQL interface #80

ShivanshJ opened this issue Jun 27, 2020 · 9 comments

Comments

@ShivanshJ
Copy link

A 'headers' bar/tab can be added in the interface to support authentication tokens and other header functionality.

Currently, other external third-party clients like Insomnia have to be downloaded.

@KingDarBoja
Copy link
Contributor

Hi @ShivanshJ

The plan is to merge flask-graphql into graphql-server-core and release it as v3 and also bring latest GraphiQL version which does support the headers option. Please take a look at graphql-python/graphql-server#49

@vallode
Copy link

vallode commented Oct 6, 2020

For the people who end up here, in the meantime you can always overwrite the graphiql template that flask-graphql uses.

GraphQLView.as_view(
    ...
    graphiql_version="1.0.5",
    graphiql_template=graphiql_template.TEMPLATE,
)

Where graphiql_template.TEMPLATE is an updated version of flask_graphql/render_graphiql.py:5
I simply used the flask-graphql template and updated react, was smooth sailing.

@KingDarBoja
Copy link
Contributor

@vallode glad it was easy to override, that's the purpose of those parameters on the GraphiQLView class.

Another example can be found at #68.

Cheers!

@leahein
Copy link

leahein commented Apr 28, 2021

For anyone looking for an updated graphiql template that supports request headers, this is a slightly tweaked version (template variables have been changed to match the variables passed in by flask-graphql), taken mostly from graphql-server.

TEMPLATE = """<!--
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_html_title}}</title>
  <meta name="robots" content="noindex" />
  <meta name="referrer" content="origin" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <style>
    body {
      margin: 0;
      overflow: hidden;
    }
    #graphiql {
      height: 100vh;
    }
  </style>
  <link href="//cdn.jsdelivr.net/npm/graphiql@{{graphiql_version}}/graphiql.css" rel="stylesheet" />
  <script src="//cdn.jsdelivr.net/npm/[email protected]/dist/polyfill.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/[email protected]/dist/unfetch.umd.js"></script>
  <script src="//cdn.jsdelivr.net/npm/[email protected]/umd/react.production.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/[email protected]/umd/react-dom.production.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/graphiql@{{graphiql_version}}/graphiql.min.js"></script>
  <script src="//cdn.jsdelivr.net/npm/[email protected]/browser/client.js"></script>
  <script src="//cdn.jsdelivr.net/npm/[email protected]/browser/client.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];
      }
    }
    // Configure the subscription client
    let subscriptionsFetcher = null;
    var fetchURL = locationQuery(otherParams);
    // Defines a GraphQL fetcher using the fetch API.
    function graphQLFetcher(graphQLParams, opts) {
      return fetch(fetchURL, {
        method: 'post',
        headers: Object.assign(
          {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
          },
          opts && opts.headers,
        ),
        body: JSON.stringify(graphQLParams),
        credentials: 'include',
      }).then(function (response) {
        return response.json();
      });
    }
    // 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 onEditHeaders(newHeaders) {
      parameters.headers = newHeaders;
      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: subscriptionsFetcher || graphQLFetcher,
        onEditQuery: onEditQuery,
        onEditVariables: onEditVariables,
        onEditHeaders: onEditHeaders,
        onEditOperationName: onEditOperationName,

        query: {{ params.query|tojson }},
        response: {{ result|tojson }},
        variables: {{ params.variables|tojson }},
        operationName: {{ params.operation_name|tojson }},

        headers: {{params.headers or ''|tojson}},
        headerEditorEnabled: true,
        shouldPersistHeaders: true,
      }),
      document.getElementById('graphiql')
    );
  </script>
</body>
</html>"""

@leahein
Copy link

leahein commented Apr 28, 2021

Separately, maintaining our own template is less than ideal -- is there an update on when flask-graphql will support this feature?

@KingDarBoja
Copy link
Contributor

Separately, maintaining our own template is less than ideal -- is there an update on when flask-graphql will support this feature?

Well yes, use graphql-server pre-release version, which supports flask, sanic, aiohttp, webob by following the flask docs

@leahein
Copy link

leahein commented Apr 29, 2021

Unfortunately I am relying on graphene-file-upload, which directly depends on flask-graphql.

Even if that wasn't the case, the graphql-server pre-release depends on graphene 3.0, and I'm also using graphene-sqlalchemy, which doesn't support that version yet.

@leahein
Copy link

leahein commented Apr 29, 2021

Since it seems like everything is being consolidated in graphql-server, does that mean flask-graphql won't be releasing newer versions?

@anatoleblanc
Copy link

Any news on a way to have a header support for flask-graphql ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants