Random memo

CORS in graphql as Firebase Cloud Function

October 18, 2018

This post is on how to solve CORS issue when deploying apollo graphql server in firebase as a cloud function.

If you want to deploy your apollo server on firebase as a cloud function, you would write your cloud function code something like this:

// imports and other settings...

const server = new ApolloServer({
  typeDefs,
  resolvers,
})

exports.graphql = functions.https.onRequest((req, res) => {
  return server.createHandler()(req, res)
})

and your web client application using react to access the graphql server would be written something like:

// imports and other settings...

const client = new ApolloClient({
  uri: "https://your_project_id.cloudfunctions.net/graphql",
})

ReactDOM.render(
  <ApolloProvider client={client}>
    <App />
  </ApolloProvider>,
  document.getElementById("root")
)

However, your web application wouldn’t work if it was loaded to your browser from other domain than your firebase function domain(for example, http://localhost:3000). This is known as CORS mechanism for security reason.

Quote from MDN:

A web application executes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, and port) than its own origin.

To enable your web app which was loaded from http://localhost:3000 for example, your graphql server running as a firebase function needs to set necessary access control headers in response, like so:

res.setHeader("Access-Control-Allow-Origin", "http://localhost:3000")
res.setHeader("Access-Control-Allow-Methods", "GET, POST")
res.setHeader("Access-Control-Allow-Headers", "origin, content-type, accept")
res.setHeader("Access-Control-Expose-Headers", "...")
res.setHeader("Access-Control-Max-Age", 600)

before you hand your response over to your HTTP handler in your firebase function.

Another way to solve the problem is using proxy. You don’t need special touch on your server code in firebase for CORS. All you have to do is prefixing your apollo client’s uri with some CORS proxy address, like so:

const proxy = "https://cors-anywhere.herokuapp.com/"

const client = new ApolloClient({
  uri: `${proxy}https://project_id.cloudfunctions.net/graphql`,
})

Sangche

Written by Sangche. Github