55

I just finished the Hello World Google Cloud Functions tutorial and received the following response headers:

Connection → keep-alive
Content-Length → 14
Content-Type → text/plain; charset=utf-8
Date → Mon, 29 Feb 2016 07:02:37 GMT
Execution-Id → XbT-WC9lXKL-0
Server → nginx

How can I add the CORS headers to be able to call my function from my website?

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
Federico Elles
  • 4,659
  • 7
  • 27
  • 35

10 Answers10

94

here we go:

exports.helloWorld = function helloWorld(req, res) {  
  res.set('Access-Control-Allow-Origin', "*")
  res.set('Access-Control-Allow-Methods', 'GET, POST');

  if (req.method === "OPTIONS") {
    // stop preflight requests here
    res.status(204).send('');
    return;
  }

  // handle full requests
  res.status(200).send('weeee!);
};

then you can jquery/whatever it as usual:

$.get(myUrl, (r) => console.log(r))
samthecodingman
  • 23,122
  • 4
  • 30
  • 54
spencercooly
  • 6,548
  • 2
  • 23
  • 15
32

I'm the product manager for Google Cloud Functions. Thanks for your question, this has been a popular request.

We don't have anything to announce just yet, but we're aware of several enhancements that need to be made to the HTTP invocation capabilities of Cloud Functions and we'll be rolling out improvements to this and many other areas in future iterations.

UPDATE:

We've improved the way you deal with HTTP in Cloud Functions. You now have full access to the HTTP Request/Response objects so you can set the appropriate CORS headers and respond to pre-flight OPTIONS requests (https://cloud.google.com/functions/docs/writing/http)

UPDATE (2022):

Just noticed there was a question about docs, and our docs have moved. Updated docs for CORS are here:

https://cloud.google.com/functions/docs/samples/functions-http-cors

Jason Polites
  • 5,571
  • 3
  • 25
  • 24
  • 22
    The link provided (https://cloud.google.com/functions/docs/writing/http) doesn't mention anything about cors. Is there any official documentation to look at? I was hoping there would be a UI to change these settings (a la aws) but there doesn't seem to be. – Ryan Mar 30 '17 at 05:22
  • 2
    Is CORS supported in the beta python environment? – lancejabr Aug 17 '18 at 00:02
  • The Python environment uses Flask as its web framework, so you should be able to manually set CORS headers using standard Flask semantics. We're gradually adding python samples where they're missing, and this is one of them. Setting headers in Flask discussed here: https://stackoverflow.com/questions/29464276/add-response-headers-to-flask-web-app – Jason Polites Aug 22 '18 at 03:51
  • documentation here is quite confusing. ttps://firebase.google.com/docs/functions/http-events . How is it related to express? – fotoflo Feb 05 '20 at 22:10
7

You can use the CORS express middleware.

package.json

npm install express --save
npm install cors --save

index.js

'use strict';

const functions = require('firebase-functions');
const express = require('express');
const cors = require('cors')({origin: true});
const app = express();

app.use(cors);
app.get('*', (req, res) => {
    res.send(`Hello, world`);
});

exports.hello = functions.https.onRequest(app);
Gary
  • 821
  • 8
  • 20
5

I've just created webfunc. It's a lightweight HTTP server that supports CORS as well as routing for Google Cloud Functions. Example:

const { serveHttp, app } = require('webfunc')

exports.yourapp = serveHttp([
  app.get('/', (req, res) => res.status(200).send('Hello World')),
  app.get('/users/{userId}', (req, res, params) => res.status(200).send(`Hello user ${params.userId}`)),
  app.get('/users/{userId}/document/{docName}', (req, res, params) => res.status(200).send(`Hello user ${params.userId}. I like your document ${params.docName}`)),
])

In your project's root, simply add a appconfig.json that looks like this:

{
  "headers": {
    "Access-Control-Allow-Methods": "GET, HEAD, OPTIONS, POST",
    "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept",
    "Access-Control-Allow-Origin": "*",
    "Access-Control-Max-Age": "1296000"
  }
}

Hope this helps.

Nicolas Dao
  • 987
  • 12
  • 22
4

In the python environment, you can use the flask request object to manage CORS requests.

def cors_enabled_function(request):
    if request.method == 'OPTIONS':
        # Allows GET requests from any origin with the Content-Type
        # header and caches preflight response for an 3600s
        headers = {
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Methods': 'GET',
            'Access-Control-Allow-Headers': 'Content-Type',
            'Access-Control-Max-Age': '3600'
        }

        return ('', 204, headers)

    # Set CORS headers for the main request
    headers = {
        'Access-Control-Allow-Origin': '*'
    }

    return ('Hello World!', 200, headers)

See the gcloud docs for more.

half-hitch
  • 173
  • 1
  • 8
4

You need to send an 'OPTIONS' response by setting its header as follows:

if (req.method === 'OPTIONS') {
  res.set('Access-Control-Allow-Methods', '*');
  res.set('Access-Control-Allow-Headers', '*');
  res.status(204).send('');
}

Runtime: NodeJS 10

ggorlen
  • 44,755
  • 7
  • 76
  • 106
Antier Solutions
  • 1,326
  • 7
  • 10
  • This is a preflight request handler. See [the docs](https://cloud.google.com/functions/docs/writing/http#functions_http_cors-nodejs) for a more in-depth explanation. – ggorlen Mar 05 '21 at 14:47
4

If you tried the accepted answer but encountered a preflight error, the docs offer examples of handling it in multiple languages, with the caveat that it only works on public functions, i.e. deployed with --allow-unauthenticated:

exports.corsEnabledFunction = (req, res) => {
  res.set("Access-Control-Allow-Origin", "*");

  if (req.method === "OPTIONS") {
    /* handle preflight OPTIONS request */
    
    res.set("Access-Control-Allow-Methods", "GET, POST");
    res.set("Access-Control-Allow-Headers", "Content-Type");

    // cache preflight response for 3600 sec
    res.set("Access-Control-Max-Age", "3600");
    
    return res.sendStatus(204);
  }

  // handle the main request
  res.send("main response");
};

Another option is to use Express as shown in this post, complete with cross-origin enabled.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
  • Note: 6 months after the original answer: the accepted answer has been edited to handle CORS, but I'll leave this up for posterity because it seems clearer. – ggorlen Aug 31 '21 at 20:04
  • This should be higher up, I haven't seen this troublesome caveat mentioned anywhere else. – Akra Jun 26 '23 at 15:33
2

You must enable CORS within all your functions, for example hello function:

index.js

const cors = require('cors')();

// My Hello Function
function hello(req, res) {
  res.status(200)
    .send('Hello, Functions');
};

// CORS and Cloud Functions export
exports.hello = (req, res) => {
  cors(req, res, () => {
    hello(req, res);
  });
}

Don't forget about package.json

package.json

{
  "name": "function-hello",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "cors": "^2.8.5"
  }
}
1

After applying your favourite answer from here, if you're still getting this error, check for uncaught errors in your cloud function. This can result in the browser receiving a CORS error, even when your error has nothing to do with CORS

Blueriver
  • 3,212
  • 3
  • 16
  • 33
0

After CORS enabled if you send POST request to your function also check for your request Content-Type header, mine was set it to "text/plain" and my browser was constantly triggering CORS errors, after setting the header to "application/json" everything worked properly.

Axel
  • 1
  • 1