41

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
  • 62,215
  • 21
  • 143
  • 153
Federico Elles
  • 4,439
  • 7
  • 25
  • 34

8 Answers8

76

here we go:

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

then you can jquery/whatever it as usual:

$.get(myUrl, (r) => console.log(r))
spencercooly
  • 6,028
  • 2
  • 20
  • 15
23

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)

Jason Polites
  • 4,967
  • 2
  • 21
  • 22
  • 20
    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
5

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
  • 721
  • 7
  • 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
  • 652
  • 7
  • 16
2

You need to send Option response and can set header in same

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

Runtime : NodeJs 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
1

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
  • 143
  • 1
  • 8
1

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

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");
};
ggorlen
  • 26,337
  • 5
  • 34
  • 50