Closed sulliwane closed 4 years ago
Download @skevy's https://github.com/skevy/graphiql-app and your header. I have the same setup as you and use this daily.
@KyleAMathews awesome, I will give it a shot (my main computer is linux distro though...). thanks
@sulliwane - I'm sure it would compile on Linux - just haven't tried.
I just tried npm install && npm start
under linux (ubuntu 14.04) and graphiql-app-V0.3.1, but got blank screen, see here: https://github.com/skevy/graphiql-app/issues/10
I close this issue as I have the answer now.
Any reason to close this issue and opposed to adding the header editor to the (main) graphiql?
No reason, indeed it would be nice if we could set the header directly into graphiql app. (I'm using graphiql-app right now.)
GraphiQL is generic and doesn't know anything about the network! This is great because you can configure it to use whatever your GraphQL server uses. This is how @skevy was able to build a standalone app version of GraphiQL.
I suggest taking a look at the example - where you see graphQLFetcher
is where you can configure your network fetching however you like, in your case by including any authentication details that may be necessary.
Often, when your GraphQL endpoint is behind a authorization feature like this, it is common to expose the GraphiQL tool via a different endpoint on your server.
@leebyron I would agree being generic is a reason not to automate everything. I would think, though, that being generic is exactly why it DOES makes sense to have a field allowing custom headers to be set manually by the user!
I'm also unclear as to your last statement. It doesn't avoid the need for auth tokens to be pushed around.
@MarkAndrewJohnson @sulliwane @cancan101 @KyleAMathews Guys, it would be interesting to get your opinion on this https://github.com/graphql/express-graphql/issues/101
I found a way to fix this problem. On Chrome, you can install an extention ModHeader
https://chrome.google.com/webstore/detail/modheader/idgpnmonknjnojddfkpgkljpfnnfcklj which will allow you to modify request or response headers. In this way, you can send Authorization header with each request and graphiql will work fine.
Look at auth-graphiql (https://github.com/vitalcode/auth-graphiql) that wraps GraphiQL providing support for bearer token and arbitrary URL. Great for testing GraphQL services secured with OAuth 2.0.
For those still having this issue, my coworker came up with a cheap solution (in Express in my case). Have your GraphiQL answer at another endpoint as Lee said above and apply basic-auth
to that, where you can supply your JWT, add it to the headers and then let express-jwt
pick it up in the next middleware.
Actually, I use a simple solution between our GraphQL development process. If you GraphQL server parse a access_token
from querystring
more than just a http header.
We can pass access_token
in query string to the browser's address bar at our GraphiQL page ?access_token=xxx&query=...
then GraphiQL will send access_token
to req.query
I parse a token with something like express-bearer-token
FWIW... In dev mode only, I've set up my server to save the most recent valid token used for the graphql endpoint, and slap it on any subsequent graphiql-driven queries (where the referer header is graphiql). I just sign into the app and then can use graphiql at will.
Easy implementation to get JWT Token support in GraphiQL
https://gist.github.com/sasso/3c3d728e0049d5b66a2c19b349b7f164
@sasso Thanks, but your old version does not support websockets :-(
Hope this helps. How I implimented custom headers for my GraphiQL interface with a express-graphql server.
Modify your server to handle post requests from one endpoint and get requests to the graphiql interface on another.
app.post(
'/graphql',
expressGraphQL({
schema: GraphQLSchema,
graphiql: false, // Disable graphiql for posts requests
}),
)
app.get(
'/graphql',
expressGraphQL({
schema: GraphQLSchema,
graphiql: true, // Enable graphiql for get requests
}),
)
Basically you need to create a new index.html for your GraphiQL interface and add it to your servers public directory i.e. <public-path>/graphql/index.html
. In that file you can modify the fetch function to send any additional headers in your requests. I got my index.html from the graphiql example.
I use webpack and the html-webpack-plugin to bundle the index.html. This allows it to get the correct version of graphql used in my project from the CDN. Below is an example of my webpack config and my ejs template of the index.html.
webpack.config.js
new HtmlWebpackPlugin({
filename: 'graphql/index.html', // Write the file to <public-path>/graphql/index.html
inject: false, // Do not inject any of your project assets into the template
GRAPHQL_VERSION: packageJSON.dependencies.graphql.replace(/[^0-9.]/g, ''), // Get the graphql version from my package.json
template: 'graphiql.ejs', // path to template
}),
graphiql.ejs
<!--
* Copyright (c) Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the license found in the
* LICENSE file in the root directory of this source tree.
-->
<!DOCTYPE html>
<html>
<head>
<style>
body {
height: 100%;
margin: 0;
width: 100%;
overflow: hidden;
}
#graphiql {
height: 100vh;
}
</style>
<!--
This GraphiQL example depends on Promise and fetch, which are available in
modern browsers, but can be "polyfilled" for older browsers.
GraphiQL itself depends on React DOM.
If you do not want to rely on a CDN, you can host these files locally or
include them directly in your favored resource bunder.
-->
<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>
<link href="//cdn.jsdelivr.net/npm/graphiql@<%= htmlWebpackPlugin.options.GRAPHQL_VERSION %>/graphiql.css" rel="stylesheet" />
<script src="//cdn.jsdelivr.net/npm/graphiql@<%= htmlWebpackPlugin.options.GRAPHQL_VERSION %>/graphiql.min.js"></script>
</head>
<body>
<div id="graphiql">Loading...</div>
<script>
/**
* This GraphiQL example illustrates how to use some of GraphiQL's props
* in order to enable reading and updating the URL parameters, making
* link sharing of queries a little bit easier.
*
* This is only one example of this kind of feature, GraphiQL exposes
* various React params to enable interesting integrations.
*/
// Parse the search string to get url parameters.
var search = window.location.search;
var parameters = {};
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));
}
});
// if variables was provided, try to format it.
if (parameters.variables) {
try {
parameters.variables =
JSON.stringify(JSON.parse(parameters.variables), null, 2);
} catch (e) {
// Do nothing, we want to display the invalid JSON as a string, rather
// than present an error.
}
}
// 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() {
var newSearch = '?' + Object.keys(parameters).filter(function (key) {
return Boolean(parameters[key]);
}).map(function (key) {
return encodeURIComponent(key) + '=' +
encodeURIComponent(parameters[key]);
}).join('&');
history.replaceState(null, null, newSearch);
}
// Defines a GraphQL fetcher using the fetch API. You're not required to
// use fetch, and could instead implement graphQLFetcher however you like,
// as long as it returns a Promise or Observable.
function graphQLFetcher(graphQLParams) {
// Get token from local storage
var token = localStorage.getItem('token')
// This example expects a GraphQL server at the path /graphql.
// Change this to point wherever you host your GraphQL server.
return fetch('/graphql', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': token ? 'Bearer '+ token : null,
},
body: JSON.stringify(graphQLParams),
credentials: 'include',
}).then(function (response) {
return response.text();
}).then(function (responseBody) {
try {
return JSON.parse(responseBody);
} catch (error) {
return responseBody;
}
});
}
// Render <GraphiQL /> into the body.
// See the README in the top level of this module to learn more about
// how you can customize GraphiQL by providing different values or
// additional child elements.
ReactDOM.render(
React.createElement(GraphiQL, {
fetcher: graphQLFetcher,
query: parameters.query,
variables: parameters.variables,
operationName: parameters.operationName,
onEditQuery: onEditQuery,
onEditVariables: onEditVariables,
onEditOperationName: onEditOperationName
}),
document.getElementById('graphiql')
);
</script>
</body>
</html>
Thanks for sharing @emjaksa.
@emjaksa Your code is working fine with query operations, what about subscriptions?...
I use passport-http-bearer
to parse token on my express server. It parses token from header as well as access_token
from query string.
So I add the access_token in the GraphQL endpoint of GraphiQL. Here is my code.
app.get('/graphiql', graphiqlExpress({ endpointURL: '/graphql?access_token=<token>&' }));
This authenticates all requests made by GraphiQL
I've ended up passing access token through Graphiql's Query Variables pane:
{ "accessToken": "azaza" }
@AndreyMalykhin You can use https://altair.sirmuel.design/ also.
@AndreyMalykhin +1 to Altair over the GraphiQL client if only for the ability to edit the headers when my tokens change (rather than deleting and re-entering them).
What about
GraphiQL::Rails.config.headers['Authorization'] = -> (context) do
"your jwt"
end
on the graphiql.rb
initializer
its really sad that this is still open after 3 years... All the solutions provided in the comments are just workarounds or reference to other tools. It shouldn't be too complicated to implement some form in the UI to add the headers.. Are there any intentions to implement this?
I'm currently using Insomnia which is like Postman for graphQL, but I'd rather just use graphiql.
@khaledosman - We have a forked version of GraphiQL which adds a header UI. It comes with a configurable endpoint and headers and is hosted online at https://graphiql-online.com.
The source of the fork is here.
Hope its helpful for some people :)
I have a question about graphene authentication...how can I create different tokens for two different logins using graphene -jwt? I want to return a token for user login and also a token for manual admin login? how can I do both?
When there will be feature to add headers for tests by default in GraphiQL ?
I got here from google search found answer in issue below - in the graphql - http headers at bottom just add
{ "Authorization": "Bearer your-token-goes-here" } https://github.com/howtographql/howtographql/issues/448
UPDATE N.B. - actually this is the wrong answer for graph-i-Ql which seems to be missing this component / I didn't realize. I've left this answer above.
You can use prisma graphql playground - https://github.com/prisma/graphql-playground This repo should probably yield to that code base / or cherry pick the headers code to get this in.
You can customize headers as they do here, with a custom fetcher: https://github.com/graphql/graphiql#getting-started
I got here from google search found answer in issue below - in the graphql - http headers at bottom just add
{ "Authorization": "Bearer your-token-goes-here" } howtographql/howtographql#448
@johndpope GraphiQL has only "Query variables" section. It does not have "http headers". How did you get that section? What type of UI do you use to test GraphQL queries?
@westpole https://github.com/absinthe-graphql/absinthe_plug/blob/master/lib/absinthe/plug/graphiql.ex
Make sure you have configured the correct interface. If you have the correct interface, there is a button you can push to access the headers functionality
I don't get why on earth we cannot have a "headers" section just like the "query variables" section. Seems awkward, now 4 years later...
@sorenhoyer The reason is that GraphQL is not a HTTP API, it's a function call. It can be consumed locally in your programming language of choice, or over a custom TCP/UDP protocol, or via HTTP, or via Websockets, or through IPC, or through any number of other transports. Headers are only used for the HTTP transport (and, possibly, for websockets, although typically they're not used there by clients). So headers are a concern outside of GraphiQL, only the fetcher
function needs to know about them, and that function also lives outside of GraphiQL. You can already add your own interface for managing headers outside of the main GraphiQL component, and you can even add a button inside of GraphiQL to open said interface - this is what I do in PostGraphile's --enhance-graphiql
mode in case you want to see an example.
In GraphiQL v1 we're planning to add a plugin system where you can easily insert these "external concerns" into the GraphiQL interface, and a preset system with sharable plugin configurations for a particular use case. We're hoping this will enable people to use a HTTP preset that will pull in common HTTP concerns such as headers, URL bar, cookie configuration, etc. so you can get the interface you want with minimal effort. We've only recently started on this project so it's still a while away (most of us are independent open source developers doing this in our spare time, and only became maintainers very recently) but progress is good.
Thanks for your elaborate answer @benjie and good luck on your future work on graphiql.
For now, for those of us in need of a graphiql-ish interface, with headers support, I can recommend: https://chrome.google.com/webstore/detail/graphiql-feen/mcbfdonlkfpbfdpimkjilhdneikhfklp
I'm really confused. In what way is graphiql useful without being able to access authorized data? Is there something I'm missing here? I can't think of any use cases in which I wouldn't eventually need to pass an auth token.
The custom fetcher allows you to prescribe any http request pattern you want, you just need to provide the prop to the component.
@SephReed the graphiql readme has several examples if you look, you just have to follow the link from the readme
I've implemented a custom fetcher, and am injecting custom ui. I had been using https://github.com/graphql/express-graphql, but it's "auto graphiql" feature is useless as vanilla graphiql. So now I'm having to reimplement a bunch of stuff.
I don't think graphiql is very useful alone. It seems you kind of have to hack it before it does what it really, really seems like it already should.
That’s not hacking it, that’s exactly how it is intended to be used.
GraphiQL is the building blocks with which you can make a custom GraphQL IDE, and has a very well defined boundary: you worry about the transport and all the transport concerns (via the fetcher function) and GraphiQL worries about the text editing and GraphQL features/documentation.
that’s exactly how it is intended to be used.
It's awful UX. I'm having to parse through this issue to get the gist, so I can look into the docs and figure out how to reimplement from scratch something which I already had running through another means, all for the sake of adding basic functionality. I get the design principle you're operating by, modularity is important. But everything in moderation.
This is what I would do:
props {
showHeaderInputComponent: boolean; // defaults to false
}
Simple, backwards compatible, easy to understand, doesn't ask the world of the user. There is no way this wouldn't be a better UX than what exists right now.
"That’s not hacking it, that’s exactly how it is intended to be used."
That sounds like a very very poor excuse not to have to do work :-) In the end; the majority of applications for graphiql require that it sends headers. The fact that it cannot do so without the user changing code is ridiculous.
This issue has been open for four years, you could save us all a ton of misery by just implementing a basic version of this feature and let whoever needs to override it do so.
I'm sorry, it's just ridiculous.
@SephReed @vinny42 The core of the GraphiQL tool isn't specific to HTTP as a transport mechanism (that's what @benjie is saying). While it is true that the majority of the cases so far have used HTTP as a transport mechanism, that is solely as a result of the use cases that exist.
On the other hand, the GraphiQL team was recently restructured and already have this implementation in mind, to make GraphiQL pluggable (https://github.com/graphql/graphiql/issues/829) such that there would be plugins providing some of these features, and also presets that bundle plugins together as they make sense for certain scenarios.
The suggestions here are for working with headers in the current GraphiQL version, and how that can be achieved. Most likely there wouldn't be any modifications to this current (soon to be old) version, and if you don't like the approaches suggested, you could consider other tools for now (there's a number of them available) until the GraphiQL v1.0.0 is released.
Final note: the members of the team maintaining GraphiQL are opensource contributors!
the members of the team maintaining GraphiQL are opensource contributors
Who runs the internal politics though? I highly doubt that everyone collectively agreed "making http easy is bad." God speed to open-source contributors, but using them as a human shield for what is almost certainly a top down decision is kind of cheap, eh?
@SephReed - would you mind laying out how we can improve and make concrete suggestions? Above you made a suggestion about using a different props structure, but I am getting a feeling that there is something overarching missing for you to ramp up on GraphiQL quickly. Open source is great, because people with different ideas come together. Therefore I value your input. I'd be more than happy to review/approve any pull requests that make it even easier to use or improve the documentation :)
Gladly.
I think it's important to have configuration and I also think it's also important to have user friendly defaults. In terms of pretty much any javascript implementation of graphiql, it seem safe to assume that a good default for fetcher is just fetch pointed at "/graphql." This definitely wouldn't cover every use case, but it's a good starting place.
Following is about all the code I think it should take to setup graphiql, with fetch, pointed to an arbitrary endpoint, with a header component added to the mix:
GraphiQL.renderIn("graphiql", {
fetcher: "/gql-endpoint",
showHeaderInputComponent: true,
});
Having 20-50 lines of boilerplate to achieve a simple api with jwt authentication is just a oppressive nuisance when it so easily could be supplied by a tiny function like the one above. This would cover most api use cases... all the ones I can think of at least, but definitely not all. Still, by default, this seems like all it should really take to get a project with graphiql up and running.
I guess what I'm really trying to say is, you've made a wonderful project. It's very nice and I don't mean to be a bother.
Is there any way to send header from Graphiql now? which something official from graphiql
@SephReed - would you mind laying out how we can improve and make concrete suggestions? Above you made a suggestion about using a different props structure, but I am getting a feeling that there is something overarching missing for you to ramp up on GraphiQL quickly. Open source is great, because people with different ideas come together. Therefore I value your input. I'd be more than happy to review/approve any pull requests that make it even easier to use or improve the documentation :)
With no way to set authentication headers the library is unusable for most people, most people don't build demo todo apps, but real world apps for customers and corporates, so authentication is kinda important.
With no workarounds or recommended way to do it in a README or a documentation file, you're pushing people away from using your open-source tools because you don't even acknowledge it as a typical normal usecase that everyone is going to stumble upon, which is why everyone else in this thread is suggesting an alternative library.
My question is, As a contributor to this library, have you ever used this tool before? have you ever needed to build authentication? if yes, how did you do it?
The cost/effort for building this is little to none compared to the benefit, yet you don't see it as something that should be part of the interface, this issue has been around for 4 years now and its only going to get more comments by more frustrated developers.
One last FYI:
We've taken the previous advice and ditched graphiql as "unusable for our purpose".
"While it is true that the majority of the cases so far have used HTTP as a transport mechanism, that is solely as a result of the use cases that exist."
Yes, the majority of use cases are HTTP, that's the point; there is no benefit to being network-protocol-agnostic and refusing to add features for HTTP in a tool that is pretty much only used over HTTP is... I'll let you fill in the bits where I might say bad things.
Thanks for the response, I hope GraphiQL will some day be a good alternative again.
My /graphql route is protected by JWT token, so every HTTP request needs to set:
To get through the authentication middleware and hit /graphql.
How to manage this authentication step when using graphiql ? graphiql is so convenient, it's a pity to not use it :( thanks for any suggestion!