Tariq
Tariq

Reputation: 41

google cloud function python CORS error No 'Access-Control-Allow-Origin' header is present on the requested resource.

Ive followed instructions at https://cloud.google.com/functions/docs/writing/http#functions_http_cors-python

So my code has this at the end

 # Set CORS headers for the preflight 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 = {
            'Content-Type':'application/json',
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Headers': 'Content-Type',
        }

        # END CORS

        return (res, 200, headers)

where res is JSON

from a simple node app, im calling via

this.http.post(payloadTarget.url, JSON.stringify(clone)).subscribe(res => {
    console.log('request complete', res);
  },
  err => {
    console.log('request failed', err);
  });

im getting this error on console

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access.

when testing a POST or OPTIONS using Postman i dont see the error but i also dont see the HEADERS im supposed to

im sure its something simple but looking at others similar questions and answers cant find anything that points to my issue

Upvotes: 4

Views: 3983

Answers (3)

Emre
Emre

Reputation: 1103

This happens when I put an annotation to the function. I added this annotation because Cloud Functions doesn't show detailed error logs for Python. My function returns expected headers when I removed the annotation.

Upvotes: 0

Adamo Figueroa
Adamo Figueroa

Reputation: 456

You could create a function that adds CORS to each response. Use jsonify to cast a dict into JSON.

from flask import jsonify

def addCors(response, code=200):
    headers = {'Access-Control-Allow-Origin': '*'}
    return (response, code, headers)

def func_with_cors(request):
    response = jsonify({"key1":"value1","key2":"value2"})
    return addCors(response)

then deploy func_with_cors

gcloud functions deploy func_with_cors --runtime python37 --trigger-http

Upvotes: 1

Matthew Merryfull
Matthew Merryfull

Reputation: 1496

I think the issue here is that you've left out the POST from your OPTIONS response. With CORS you'll need to be specific about which http methods are acceptable. With that being said, you'll need to update your pre-flight request to:

    # Set CORS headers for the preflight 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, POST',
            'Access-Control-Allow-Headers': 'Content-Type',
            'Access-Control-Max-Age': '3600'
        }

        return ('', 204, headers)

    # Set CORS headers for the main request
    headers = {
        'Content-Type':'application/json',
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Headers': 'Content-Type',
    }

    # END CORS

    return (res, 200, headers)

Alternatively, you can set the value to:

'Access-Control-Allow-Methods': '*'

If you aren't that concerned with security.

Also, the reason you're not getting these errors via POSTMAN is due to the nature of the request - All modern browsers intercept your request and check to see if the origins match (domain, port, protocol, etc), if they don't, a pre-flight (OPTIONS) request is made to the the destination to make sure that its okay. Sites like POSTMAN and software like Fiddler aren't initiated from the browser and are submitted without any checks.

Upvotes: 4

Related Questions