-
Notifications
You must be signed in to change notification settings - Fork 536
Support CORS enabled servers and OPTIONS requests #14
Comments
Sorry for the delay! I think option #2 is probably the right thing to do. Ideally express-graphql is agnostic to CORS. I'm happy to entertain PRs for this. |
@leebyron no apologies needed, I know you must be swamped. So the question I have is, how do we do that? An If Maybe it'd be best to rely on the user to catch |
This sounds right to me. I haven't implemented CORS before, so I'm not actually sure what is required to make it happen. If this is something that can be 100% done by middleware ahead of |
Yeah I'm going to go ahead and close this after thinking about it more, the user should know to respond to |
Let me know if you learn more about enabling this with Express — On Wed, Sep 30, 2015 at 8:04 PM, Brandon Dail [email protected]
|
Well enabling it in Express is easy. There's the cors middleware package, or you just set the appropriate access headers. It's just that it should be implemented as its own middleware meaning we just don't need to worry about it. |
I'm still seeing
Does Edit: I guess not. An example would have been nice; I'm not using express for anything other than serving GraphQL so I don't have a lot of experience with it. |
Correct, express-graphql only implements the graphql endpoint behavior and nothing more. To enable CORS for your express server you have to handle the OPTIONS request yourself. I'm open to ideas on how to support CORS out of the box, but so far the feeling is that this would be a dangerous thing to do |
Would it be dangerous to just make it an option, defaulting to That way us dummies that don't know anything about express or CORS could just quickly set it to |
Okay, I got CORS working for my needs. Here's a full(ish) example for anyone else who stumbles upon this: import express from 'express';
import graphqlHttp from 'express-graphql';
const port = 8080;
const app = express();
const schema = require('schema/schema.js');
const Chalk = require('chalk');
const cors = require('cors');
app.use('/graphi',express.static(`${__dirname}/public`)); // we could have just used the `graphiql` option: https://github.com/graphql/express-graphql
app.use('/graphql', cors(), graphqlHttp(() => ({
schema: schema
})));
app.listen(port);
console.log(`Started on ${Chalk.underline.blue(`http://localhost:${port}/`)}`); |
This bit me hard. Took me a while to figure out what was going on. Here's what I found after copying a few requests from GraphiQL and comparing to my own. fetch('http://localhost:4000/graphql?', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
query: "{entries {id}}"
})
})
.then((res) => res.json())
.then((data) => console.log(data))
.catch((err) => { console.log(err); });
// Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
// OPTIONS http://localhost:4000/graphql? (anonymous function)
// localhost/:1 Fetch API cannot load http://localhost:4000/graphql?. Response for preflight has invalid HTTP status code 405
// TypeError: Failed to fetch(…) The What we're handling on the This means that during a request made with the method I agree with the discussion above that it should not be this library's concern to deal with CORS, however I think that we could add some improvements through:
|
@waltfy I think there should definitely be an example in the README showing how to deal with CORS. I realize it's out of scope for this project, but a lot of people are going to have this question and pointing them in the right direction would be a big help. Adding a special error message for "OPTIONS" somewhere around here probably wouldn't be too much work either. |
@mnpenner ok, I'll open up a PR and get some feedback from more people — it certainly feels like it would be helpful from a developer experience point of view. Thanks for the feedback! |
@waltfy I am trying to run through the demo using a a node-express server and fetch instead of XHR. I am hitting this issue, but not sure how to work around it. Is there a way I can craft my fetch request to work around this issue? Thanks!! |
@waltfy - I got this working by enabling cors . also @mnpenner got it working as shown above. I had read his post but didn't really grock it because my knowledge of node/express is pretty minimal still. app.options('/graphql', cors()) |
A simple way without use of the app.use("/graphql", function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
if (req.method === 'OPTIONS') {
res.sendStatus(200);
} else {
next();
}
});
app.use('/graphql', graphQLHTTP({ schema })); |
Why all the above solutions do not work for me? |
@nicolasxu, maybe if you provide some information someone could help you :) Like what errors you're seeing on the Network tab when the requests fail, that would be a good place to start. Also how you're setting up the GraphQL route and the CORS middleware. |
HI, I have used both the solutions First one which is provided by @mnpenner
My request got stuck in pre-flight and never propagate to next request which is POST For the second solution which is provided by @EdwardAA My code looks like
My response I have 200 OK but it still got stuck in there. I am trying to access from mobile application ionic-angular Am I doing anything wrong? |
Try more headers: graphQLServer.use("/graphql", function (req, res, next) {
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Headers', 'content-type, authorization, content-length, x-requested-with, accept, origin');
res.header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
res.header('Access-Control-Allow-Origin', '*');
...
} |
@EdwardAA I have tried by adding more headers but still I am getting the same result :( |
Hello all, please excuse me for popping up with comment to very old thread. I have kinda similar situation, but without Express. Maybe this is silly, because I've recently started playing w/ GraphQL and GitHub API v4, but here is what I've faced/discovered. If I use let queryBody = {
"query": `{
repositoryOwner(login: "alundiak") {
repositories(first: 30) {
edges {
org: node {
name
}
}
}
}
}`
};
let options = {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(queryBody)
}
fetch('https://api.github.com/graphql?access_token=MY_GITHUB_TOKEN', options)
.then(response => response.json())
.then(data => {
console.log(data); // valid response received
}); But when I omit ...
let options = {
method: 'post',
body: JSON.stringify(queryBody)
}
... I also receive my needed response from server, but then request has been One more time, sorry if this not quite relevant, but it was interesting I faced with this, and reading this thread helped me to figure out what exactly is going on... |
@alundiak I just tested your code with the Content-Type header -- it sent two requests: OPTIONS followed by POST. Response data came back fine. Sent it again, only did once request. Tried without header, again, one request. It's not very relevant though -- GitHub has implemented the CORS for you. There's nothing you have to do. |
@mnpenner in fact, I see, that is the same query/url/code/approach, and using Fetch API it goes as |
@waltfy thanks!, It was very helpful, use the code to refresh my access tokens and refetch me request. I have to refactor my code const authMiddleware = new ApolloLink((operation, forward) => {
const userType = redirectionAuth.getUserType(window.location.pathname) // obteniendo el tipo de usuario
const tokensUser = tokens.getTokens(userType)
let accessToken = null
let refreshToken = null
if(tokensUser) {
accessToken = tokensUser.access_token
refreshToken = tokensUser.refresh_token
}
const observer = forward(operation)
const request = {
...operation,
query: print(operation.query)
}
return new Observable(observer => {
fetch(Config.REACT_APP_URL, {
method: 'POST',
headers: {
'content-type': 'application/json',
authorization: 'Bearer' + accessToken || null,
refresh_token: refreshToken || null
},
body: JSON.stringify({
query: request.query,
variables: request.variables
})
}).then((res) => res.json())
.then((data) => {
if(data.errors) {
console.log(data.errors)
}
if (!observer.closed) {
observer.next(data);
observer.complete();
}
}).catch((error) => {
if (!observer.closed) {
observer.error(error);
}
});
})
}) |
Hello all, app.use('/graphql',(req,res,next)=>{
res.header('Access-Control-Allow-Credentials', true);
res.header('Access-Control-Allow-Headers', 'content-type, authorization, content-length, x-requested-with, accept, origin');
res.header('Access-Control-Allow-Methods', 'POST, GET, OPTIONS')
res.header('Allow', 'POST, GET, OPTIONS')
res.header('Access-Control-Allow-Origin', '*');
if (req.method === 'OPTIONS') {
res.sendStatus(200);
} else {
next();
}
}, expressGraphQL({
schema,
graphiql: true
})); |
FYI using Express & Apollo Server v2+ I have the following config working well:
|
any example for Java to support OPTIONS on graphql server side . I am using spring boot with spring cloud adaptor for Azure |
For me following hacks worked,
PS: Worked with package versions-
|
Reading this helped me understand better how things go back and forth to solve my problem thank you! |
I'm currently trying to query the github graphql api but I have been encoutering CORS issue. How do I solve that, please? BTW, I have tried using Heroku middleware but gives a 429 [too many requests] error or unauthorized... |
Tried all the solutions mentioned above but still I get this error :
Here is the code i am using for the middleware :
By the way i don't know if this was necessary but i am using apolloServer and on frontend urql |
If you are using the cors middleware, you don't need to specify the CORS headers again. That would likely be conflicting with the settings from the middleware. Also did you first try just adding the |
I'll try and get back, thanks for the solution |
Not working |
Hi
I have the same issue, tried with your solution but this fetch works sometime and sometime
tried with different way that but no luck on that
** Could you please help me out on this |
Hi @mnpenner ,
could you please help me out |
Currently if the Express app enables CORS
express-graphql
will fail due to the above check sending a405
error when theOPTIONS
request comes in.Two options I see:
express-graphql
and enableOPTION
support whentrue
OPTION
requests by defaultI'd be happy to implement either, or another option, pending approval!
The text was updated successfully, but these errors were encountered: