apollo-server-express CORS issue
Solution 1
From my understanding of the Apollo Server middleware API, CORS options, body-parser options and the graphql endpoint are treated as special entities that must be passed directly to the applyMiddleware
param object.
So you want to try the following configuration:
const app = express();
// CORS configuration
const corsOptions = {
origin: 'http://localhost:3000',
credentials: true
}
// The following is not needed, CORS middleware will be applied
// using the Apollo Server's middleware API (see further below)
// app.use(cors(corsOptions))
// Setup JWT authentication middleware
app.use(async (req, res, next) => {
const token = req.headers['authorization'];
if(token !== "null"){
try {
const currentUser = await jwt.verify(token, process.env.SECRET)
req.currentUser = currentUser
} catch(e) {
console.error(e);
}
}
next();
});
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => ({ Property, User, currentUser: req.currentUser })
});
// There is no need to explicitly define the 'path' option in
// the configuration object as '/graphql' is the default endpoint
// If you planned on using a different endpoint location,
// this is where you would define it.
server.applyMiddleware({ app, cors: corsOptions });
const PORT = process.env.PORT || 4000;
app.listen(PORT, () => {
console.log(`Server listening on ${PORT}`);
})
Solution 2
With Apollo Server 2.x you supply the cors
field in the constructor of ApolloServer
.
So in your case, it should look like the following:
const corsOptions = {
origin: 'http://localhost:3000',
credentials: true
}
// Setup JWT authentication middleware
app.use(async (req, res, next) => {
const token = req.headers['authorization'];
if(token !== "null"){
try {
const currentUser = await jwt.verify(token, process.env.SECRET)
req.currentUser = currentUser
} catch(e) {
console.error(e);
}
}
next();
});
const server = new ApolloServer({
typeDefs,
cors: cors(corsOptions),
resolvers,
context: ({ req }) => ({ Property, User, currentUser: req.currentUser })
});
server.applyMiddleware({ app });
const PORT = process.env.PORT || 4000;
app.listen(PORT, () => {
console.log(`Server listening on ${PORT}`);
})
Here you find all params accepted by the apollo server: https://www.apollographql.com/docs/apollo-server/api/apollo-server.html#Parameters-2
Here you find the relevant discussion: https://github.com/apollographql/apollo-server/issues/1142
Solution 3
By default, the express middleware will instantiate cors middleware with default options on the graphql path, overriding any cors middleware configuration you yourself have specified for other paths(!)
You can override the defaults when you apply the apollo middleware, e.g.
apollo.applyMiddleware({ app, cors: {credentials: true, origin: true} })
I'm using apollo-server-express 2.17
Solution 4
The CORS settings come from ExpressJS, not from ApolloServer. If you want to add a custom or wildcard origin you have to handle it with a callback/handler function.
const server = new ApolloServer({
....,
cors: {
credentials: true,
origin: (origin, callback) => {
const whitelist = [
"http://site1.com",
"https://site2.com"
];
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error("Not allowed by CORS"))
}
}
}
});
Related videos on Youtube
Comments
-
José Del Valle almost 2 years
So I am migrating to apollo-server-express 2.3.3 ( I was using 1.3.6 ) I've followed several guides, making the necessary tweaks but am stuck in a CORS issue.
According to the docs you have to use the applyMiddleware function to wire up the apollo server with express.
I am currently doing the following:
const app = express(); // CORS configuration const corsOptions = { origin: 'http://localhost:3000', credentials: true } app.use(cors(corsOptions)) // Setup JWT authentication middleware app.use(async (req, res, next) => { const token = req.headers['authorization']; if(token !== "null"){ try { const currentUser = await jwt.verify(token, process.env.SECRET) req.currentUser = currentUser } catch(e) { console.error(e); } } next(); }); const server = new ApolloServer({ typeDefs, resolvers, context: ({ req }) => ({ Property, User, currentUser: req.currentUser }) }); server.applyMiddleware({ app }); const PORT = process.env.PORT || 4000; app.listen(PORT, () => { console.log(`Server listening on ${PORT}`); })
For some reason my express middleware doesn't seem to be executing, when I try to do a request from localhost:3000 (client app) I get the typical CORS error
With apollo-server-express 1.3.6 I was doing the following without no issues:
app.use( '/graphql', graphqlUploadExpress({ maxFileSize: 10000000, maxFiles: 10 }), bodyParser.json(), graphqlExpress(({ currentUser }) => ({ schema, context: { // Pass Mongoose models Property, User, currentUser } })) );
Now with the new version, event though the docs make this look like a straightforward migration, I don't seem to be able to make it work. I've checked various articles and no one seems to be having the issue.
-
Davey about 5 yearsI think this should be the accepted answer. It's the only answer that worked for me.
-
Karel Frajták about 5 yearsThe latest version of
apollo-server
(2.4.8) will throw an error whenapplyMiddleware
method is called:"To use Apollo Server with an existing express application, please use apollo-server-express"
-
Thomas Hennes about 5 years@KarelFrajták yes, the
applyMiddleware
method is provided byapollo-server-{integration}
packages as stated by apollographql.com/docs/apollo-server/api/… -
Thomas Hennes about 5 years@KarelFrajták to be clear, I didn't mention the need for that package as the OP stated he WAS using
apollo-server-express
, which provides the method -
Karel Frajták about 5 years@Jaxx I just run into similar issue and also there was confusion on respective GitHub pages
-
sznrbrt almost 5 yearsUsing
"apollo-client": "^2.5.1"
and this is the solution that worked. Only pay attention to that if you are usingapollo-upload-client
for the client link, thecreateUploadLink
method takes fetchOptions param, where you define thecredentials: 'include'
-
t3__rry almost 4 yearsThank you very much it's saved me @ThomasHennes. I'll update the docs this should definitely be written somewhere