# Enabling CORS for Express-GraphQL & Apollo Server | Prisma URL: https://www.prisma.io/blog/enabling-cors-for-express-graphql-apollo-server-1ef999bfb38d Published: 2017-11-22 Authors: Nikolas Burk Description: Learn how to enable CORS in Express-GraphQL and Apollo Server so browser clients can safely call your GraphQL API across origins. > Blog posts describe Prisma as it was on the date shown and are not kept current. Before implementing from a post, check the documentation index at https://www.prisma.io/docs/llms.txt and the changelog at https://www.prisma.io/changelog.md. > For an index of every published post, fetch https://www.prisma.io/blog/llms.txt. Learn how to configure cross-origin resource sharing on your express-based GraphQL servers. ## What is CORS? [#what-is-cors] *Cross-origin resource sharing*, short [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing), is a protection mechanism for web pages, allowing the browser to safely load resources from domains that are different from the one it originally loaded the page from. As an example, say you’re accessing `https://www.prisma.io/` in your browser. The browser downloads the HTML and JavaScript for the site in order to render it for you. Now, some data to be displayed on the site actually is stored somewhere else, on a different server — a *different origin*. > Two URLs are said to have the same origin if the following three properties are identical for them: domain, protocol and port: > `http://localhost:3000`, `ws://localhost:3000` and `http://localhost:4000` all have **different origins**. > `http://localhost:3000` and `http://localhost:3000/graphql` have the **same origin**. In order for your browser to load the data from that other server, the other server needs to set `Access-Control` headers properly in order to determine its policy regarding cross-origin resource access. For example, by simply specifying `Access-Control-Allow-Origin: *`, the server indicates to the browser that it will allow CORS anywhere. ## How about an example [#how-about-an-example] Now, imagine the following scenario. You’re starting out with a new project and for now are only developing locally on your machine. You used [`create-react-app`](https://github.com/facebookincubator/create-react-app) to bootstrap your frontend and for the backend you setup a simple [express.js](https://github.com/expressjs) server (either based on [`express-graphql`](https://github.com/graphql/express-graphql), [`graphql-yoga`](https://github.com/prismagraphql/graphql-yoga) or [`apollo-server`](https://github.com/apollographql/apollo-server)). In fact, we prepared an [example](https://github.com/nikolasburk/graphql-cors-example) that mimics this exact scenario: ### Server [#server] ```js const express = require('express') const bodyParser = require('body-parser') const cors = require('cors') const { graphqlExpress, graphiqlExpress } = require('apollo-server-express') const { makeExecutableSchema } = require('graphql-tools') const typeDefs = ` type Query { hello(name: String): String! } ` const resolvers = { Query: { hello: (_, { name }) => `Hello ${name || 'World'}`, }, } const myGraphQLSchema = makeExecutableSchema({ typeDefs, resolvers }) const PORT = 4000 const app = express() // app.use(cors()) // not having cors enabled will cause an access control error app.use('/graphql', bodyParser.json(), graphqlExpress({ schema: myGraphQLSchema })) app.get('/graphiql', graphiqlExpress({ endpointURL: '/graphql' })) console.log(`Server listening on http://localhost:${PORT} ...`) app.listen(PORT) ``` > Notice that line 23 is commented out — CORS is not enabled! ### Frontend [#frontend] ```js import React from 'react' import ReactDOM from 'react-dom' import './index.css' import App from './App' import registerServiceWorker from './registerServiceWorker' import { ApolloProvider } from 'react-apollo' import { ApolloClient, HttpLink, InMemoryCache } from 'apollo-client-preset' const httpLink = new HttpLink({ uri: 'http://localhost:4000/graphql' }) const client = new ApolloClient({ link: httpLink, cache: new InMemoryCache(), }) ReactDOM.render( , document.getElementById('root'), ) registerServiceWorker() ``` > Standard setup for using Apollo Client 2.0 ```js import React, { Component } from 'react' import logo from './logo.svg' import './App.css' import gql from 'graphql-tag' import { graphql } from 'react-apollo' class App extends Component { render() { if (this.props.data.loading) { return
Loading
} return (

{this.props.data.hello}

) } } export default graphql( gql` { hello } `, )(App) ``` > The `App` component sends a simple `hello` query using Apollo Client In your local development setup, where the React app is loaded from [`http://localhost:3000`](http://localhost:3000) and the GraphQL server is serving at [`http://localhost:4000`](http://localhost:4000)/graphql, you’ll now get an access control error if you’re trying to run the app: ![](https://www.prisma.io/blog/enabling-cors-for-express-graphql-apollo-server-1ef999bfb38d/imgs/1-ZbsVGATAeIp5iU2504VP2A.png) What exactly is the issue when CORS is not enabled? Well, CORS is in fact a *specification* for a communication flow between client (a browser) and server. In some situations, this flow requires the server to process HTTP [OPTIONS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS) requests as can be seen from this flowchart: ![The CORS flow might required additional HTTP requests with the OPTIONS method (source)](https://www.prisma.io/blog/enabling-cors-for-express-graphql-apollo-server-1ef999bfb38d/imgs/1-m6QGz5tXtLt7uVapNCpBEw.png)*The CORS flow might required additional HTTP requests with the [OPTIONS](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS.png) method ([source](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing#/media/File\:Flowchart_showing_Simple_and_Preflight_XHR.svg))* The problem is that neither `express-graphql` nor `apollo-server` accept HTTP requests other than GET and POST — which is why the request fails in our scenario. This is also indicated by the error message we saw in the console: `OPTIONS [http://localhost:4000](http://localhost:4000) 405 (Method not allowed)`. > [Here](https://github.com/graphql/express-graphql/issues/14) is the GitHub discussion on `express-graphql` where this issue first came up\*\*.\*\* Luckily, the solution is very simple. As `express-graphql` and `apollo-server` are both based on [express.js](https://github.com/expressjs), you can simply use its standard [cors](https://github.com/expressjs/cors#configuration-options) middleware to fix the issue. Uncommenting [line 23](https://github.com/nikolasburk/graphql-cors-example/blob/master/server/index.js#L23) in `server.js` will enable the cors middleware for your express server: `app.use(cors())`. Having the middleware enabled ensures your express server sets the proper HTTP header, enabling your React app to load data from it: ![Using the cors middleware, the server sets the correct HTTP header enabling cross-origin resource sharing](https://www.prisma.io/blog/enabling-cors-for-express-graphql-apollo-server-1ef999bfb38d/imgs/1-LnVsDQuQtSl-Wt-m6DfO5g.png)*Using the [cors](https://github.com/expressjs/cors) middleware, the server sets the correct HTTP header enabling cross-origin resource sharing* ## Summary [#summary] CORS is an important protection mechanism preventing websites from downloading malicious resources, but from a developer standpoint [it can be a pain to properly configure it](https://devrant.com/rants/133438/i-seriously-dont-understand-cors-fml-i-tried-to-access-the-web-api-i-found-onlin). When using `express-graphql` and `apollo-server`, all you need to do is include the standard [cors](https://github.com/expressjs/cors) middleware used in express.js apps and you’re good to go: ```js // other imports ... const cors = require('cors') const app = express() app.use(cors()) // enable `cors` to set HTTP response header: Access-Control-Allow-Origin: * app.use('/graphql', bodyParser.json(), graphqlExpress({ schema })) app.listen(PORT) ```