Comments (37)
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}/`)}`);
from express-graphql.
A simple way without use of the cors
module:
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 }));
from express-graphql.
Hello all,
just to share:
this code totally solved my problem (related to method OPTIONS not allowed)
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
}));
from express-graphql.
@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())
app.use('/graphql', graphqlHTTP({
schema: schema,
rootValue: root,
graphiql: true,
}));
from express-graphql.
Why all the above solutions do not work for me?
from express-graphql.
FYI using Express & Apollo Server v2+ I have the following config working well:
const cors = require('cors')
...
app.use(cors({
origin: '*',
methods: 'GET,HEAD,PUT,PATCH,POST,DELETE,OPTIONS',
optionsSuccessStatus: 200 /* some legacy browsers (IE11, various SmartTVs) choke on 204 */,
}))
...
from express-graphql.
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
from express-graphql.
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 TypeError
experienced above is due to the fact that the OPTIONS
(CORS pre-flight) request has failed since GraphQL only accepts GET
and POST
requests.
What we're handling on the catch
part of the Promise chain above is the failure of the OPTIONS
request not the POST
request as one may expect.
This means that during a request made with the method OPTIONS
we do not get to see in the browser the error that the library emits. This makes this simple issue really obscure.
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:
- Better logging; the library could warn the developer regarding the handling of unsupported requests.
- Better documentation on the README regarding dealing with CORS.
from express-graphql.
@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!
from express-graphql.
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', '*');
...
}
from express-graphql.
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 header
section, and content type json in particular, then request goes as OPTIONS
, but response (edges) is received from server.
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 header
section and leave body the same:
...
let options = {
method: 'post',
body: JSON.stringify(queryBody)
}
...
I also receive my needed response from server, but then request has been POST
and I also see my Request Payload:
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...
from express-graphql.
For me following hacks worked,
//Allow cors
// app.use(cors);//as per docs but not worked
// app.use(cors()); // this worked
// app.use('/graphql',cors());//this also worked
app.use(
'/graphql',
cors(), //this also worked
graphqlHTTP({
schema, //name of the schema
graphiql: true //enable client to make query to server
})
);
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server running on port ${port}`));
PS: Worked with package versions-
"cors": "2.8.5",
"express": "4.17.1",
"express-graphql": "0.9.0",
"graphql": "14.5.8"
from express-graphql.
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.
from express-graphql.
@leebyron no apologies needed, I know you must be swamped. So the question I have is, how do we do that? An OPTIONS
request should respond with the CORS headers, meaning ideally the user would catch OPTIONS
requests before letting the request fall through to express-graphql
.
If express-graphql
responds with any headers its by definition not being agnostic, so I'm curious how we can support both cases without a flag indicating how to respond.
Maybe it'd be best to rely on the user to catch OPTIONS
request in middleware up the stack before it gets to express-graphql
.
from express-graphql.
Maybe it'd be best to rely on the user to catch OPTIONS request in middleware up the stack before it gets to express-graphql.
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 express-graphql
then that is ideal and I'm happy to link to or include an example illustrating that. Otherwise if this module itself needs some slight change to work happily with a CORS middleware, I'd like to know what that would look like.
from express-graphql.
Yeah I'm going to go ahead and close this after thinking about it more, the user should know to respond to OPTIONS
requests with the appropriate headers if they're enabling CORS and it's too messy and dangerous to try and support it "out of the box".
from express-graphql.
Let me know if you learn more about enabling this with Express
—
Sent from Mailbox
On Wed, Sep 30, 2015 at 8:04 PM, Brandon Dail [email protected]
wrote:
Yeah I'm going to go ahead and close this after thinking about it more, the user should know to respond to
OPTIONS
requests with the appropriate headers if they're enabling CORS and it's too messy and dangerous to try and support it "out of the box".Reply to this email directly or view it on GitHub:
#14 (comment)
from express-graphql.
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.
from express-graphql.
I'm still seeing
Request URL:http://localhost:8080/graphql
Request Method:OPTIONS
Status Code:405 Method Not Allowed
Does express-graphql
support CORS out of box now or not? Is there an option I have to enable?
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.
from express-graphql.
Would it be dangerous to just make it an option, defaulting to false
? true
would mean enable for all requests to the /graphql route, and anything else could be delegated to cors or some other library?
That way us dummies that don't know anything about express or CORS could just quickly set it to true
for testing, and then when we need advanced whitelisting or what have you, we can fine-tune the options?
from express-graphql.
@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.
from express-graphql.
@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!!
from express-graphql.
@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.
from express-graphql.
HI,
I have used both the solutions
First one which is provided by @mnpenner
import express from 'express';
import { graphqlExpress, graphiqlExpress } from 'apollo-server-express';
import bodyParser from 'body-parser';
import { makeExecutableSchema } from 'graphql-tools';
import graphqlHttp from 'express-graphql';
var cors = require('cors');
const graphqlHTTP = require('express-graphql');
const GRAPHQL_PORT = 4400;
import typeDefs from './data/types';
import resolvers from './data/resolvers';
const schema = makeExecutableSchema({ typeDefs, resolvers });
const graphQLServer = express();
graphQLServer.use('/graphql', cors(), graphqlHttp(() => ({
schema: schema
})));
// graphQLServer.use('/graphql', bodyParser.json(), graphqlExpress({schema}));
graphQLServer.use('/graphiql', graphiqlExpress({ endpointURL: '/graphql' }));
graphQLServer.listen(GRAPHQL_PORT, () => console.log(
`GraphiQL is now running on http://localhost:${GRAPHQL_PORT}/graphiql`
));
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
import express from 'express';
import { graphqlExpress, graphiqlExpress } from 'apollo-server-express';
import bodyParser from 'body-parser';
import { makeExecutableSchema } from 'graphql-tools';
import graphqlHttp from 'express-graphql';
var cors = require('cors');
const graphqlHTTP = require('express-graphql');
const GRAPHQL_PORT = 4400;
import typeDefs from './data/types';
import resolvers from './data/resolvers';
const schema = makeExecutableSchema({ typeDefs, resolvers });
const graphQLServer = express();
graphQLServer.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();
}
});
graphQLServer.use('/graphql', cors(), graphqlHttp(() => ({
schema: schema
})));
// graphQLServer.use('/graphql', bodyParser.json(), graphqlExpress({schema}));
graphQLServer.use('/graphiql', graphiqlExpress({ endpointURL: '/graphql' }));
graphQLServer.listen(GRAPHQL_PORT, () => console.log(
`GraphiQL is now running on http://localhost:${GRAPHQL_PORT}/graphiql`
));
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?
from express-graphql.
@EdwardAA I have tried by adding more headers but still I am getting the same result :(
Moreover I have tried app.use('*', cors())
didn't work this as well.
from express-graphql.
@alundiak Content-Type
shouldn't matter. It only has to do the pre-flight OPTIONS request once -- perhaps that's why you're seeing it go straight to POST when you run it a second time without the header?
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.
from express-graphql.
@mnpenner in fact, I see, that is the same query/url/code/approach, and using Fetch API it goes as OPTIONS
and only one request and data received. But when I use XmlHttpRequest then I have 2 OPTIONS
and followed POST request. Looks like it's rather diff. between Fetch API and ajax.
from express-graphql.
@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);
}
});
})
})
from express-graphql.
any example for Java to support OPTIONS on graphql server side . I am using spring boot with spring cloud adaptor for Azure
from express-graphql.
@alundiak
Content-Type
shouldn't matter. It only has to do the pre-flight OPTIONS request once -- perhaps that's why you're seeing it go straight to POST when you run it a second time without the header?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.
Reading this helped me understand better how things go back and forth to solve my problem thank you!
from express-graphql.
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...
from express-graphql.
Tried all the solutions mentioned above but still I get this error :
Access to fetch at 'https://api-goloop.vercel.app/graphql' from origin 'https://goloop.vercel.app' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Here is the code i am using for the middleware :
const app = express();
app.use(
"/graphql",
cors({
origin: process.env.FRONTEND_URL!,
credentials: true,
}),
(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", "https://goloop.vercel.app/");
if (req.method === "OPTIONS") {
res.sendStatus(200);
} else {
next();
}
}
);
By the way i don't know if this was necessary but i am using apolloServer and on frontend urql
from express-graphql.
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 cors()
without parameters? This should allow ALL requests. If that works, then you can add the cors
options to limit it to a domain.
from express-graphql.
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
cors()
without parameters? This should allow ALL requests. If that works, then you can add thecors
options to limit it to a domain.
I'll try and get back, thanks for the solution
from express-graphql.
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
cors()
without parameters? This should allow ALL requests. If that works, then you can add thecors
options to limit it to a domain.
Not working
The problem was i was setting cors : false
in applyMiddleWare. After fixing that it works
from express-graphql.
Hi
cors()
I have the same issue, tried with your solution but this fetch works sometime and sometime
this is my server.ts file
app.use('/graphql', cors() ,graphqlHTTP({ schema,graphiql:true }));
tried with different way that but no luck on that
// const corsOptions = {
// origin: "http://localhost:3000",
// credentials: true
// };
// app.use(cors(corsOptions));// enable `cors` to set HTTP response header:
**
"message": "Failed to fetch",
"stack": "TypeError: Failed to fetch\n at graphQLFetcher (http://localhost:4000/graphql?**
Could you please help me out on this
from express-graphql.
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}/`)}`);
Hi @mnpenner ,
I have done with the same but same issue
"message": "Failed to fetch",
"stack": "TypeError: Failed to fetch\n at graphQLFetcher
could you please help me out
from express-graphql.
Related Issues (20)
- depth-limit HOT 1
- Is there a way to customize a logger HOT 1
- Unhandled errors does not provide mutation or query name HOT 1
- Graphiql playground not displayed in the browser HOT 1
- UnhandledPromiseRejectionWarning: Unhandled promise rejection HOT 1
- Why isn't the callback of app.listen() called when using express-graphql middleware? HOT 4
- Build when installed from GitHub HOT 1
- throw new MiddlewareError(`Type ${type} exists in middleware but is missing in Schema.`);
- TypeScript - merge declarations for request and response types
- Cannot install with graphql 16.0.1 HOT 10
- Update GraphQL Schema at runtime HOT 4
- Graphql 16.2.0 support HOT 9
- Processing timeout HOT 1
- About compatible version for an old graphql and node
- Swallow GraphQL errors by Express HOT 6
- Peer dependency error on new installation of graphql HOT 8
- Unmet Peer version, need to update supported dependencies HOT 9
- revert revert "Allow custom handling of runtime query errors" HOT 1
- Unable to find Prisma Client in GraphQL context. Please provide it under the `context[\"prisma\"]` key. HOT 1
- Support for running method on every call
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from express-graphql.