aryeh
aryeh

Reputation: 41

GCP Cloud Function HTTP trigger "No 'Access-Control-Allow-Origin' header is present on the requested resource." error

I have a GCP Cloud function with an HTTP trigger. I made a test react frontend that needs to trigger this function with a HTTP request.

Here is the code that makes that request:

    async function handleSubmit() {
        const url = 'https://us-central1-{project-id}.cloudfunctions.net/hello-test';
        const data = {name:"Jane"};

        const response = await fetch(url, {
            method: 'POST', // or 'PUT'
            body: JSON.stringify(data), // data can be `string` or {object}!
            headers: {
                'Content-Type': 'application/json'
            }
        });
        await response.json();

    }

Here is the cloud function:

def hello_http(request):
    # Set CORS headers for preflight requests
    if request.method == 'OPTIONS':
        # Allows GET requests from origin http://localhost:3000 with
        # Authorization header
        headers = {
            'Access-Control-Allow-Origin': 'http://localhost:3000',
            'Access-Control-Allow-Methods': 'POST', #GET???
            'Access-Control-Allow-Headers': 'Authorization',
            'Access-Control-Max-Age': '3600',
            'Access-Control-Allow-Credentials': 'true'
        }
        return ('test return value')

    # Set CORS headers for main requests
    headers = {
        'Access-Control-Allow-Origin': 'http://localhost:3000',
        'Access-Control-Allow-Credentials': 'true'
    }

    return ('another test return value')

Here is the error I get when I run this code from my local react app:

Access to fetch at 'https://us-central1-{PROJECT-ID}.cloudfunctions.net/hello-test' 
from origin 'http://localhost:3000' has been blocked by CORS policy: Response to 
preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' 
header is present on the requested resource. If an opaque response serves your needs,
 set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

This cloud function works as expected when I use:

curl -X POST HTTP_TRIGGER_ENDPOINT -H "Content-Type:application/json" -d '{"name":"Jane"}'

Any help with getting this request to work with a data object sent as a POST request and a string returned from the cloud function will solve my problem.

Thank you.

Edit: the result of curl -i -X OPTIONS {url}

Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Authorization
Access-Control-Allow-Methods: POST
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Max-Age: 3600
Content-Type: text/html; charset=utf-8
Function-Execution-Id: roz4rhywam83
X-Cloud-Trace-Context: 9d52fb9b30e029f32c2a787ad0d006d2;o=1
Date: Thu, 21 Nov 2019 20:03:54 GMT
Server: Google Frontend
Content-Length: 15
Alt-Svc: quic=":443"; ma=2592000; v="46,43",h3-Q050=":443"; ma=2592000,h3-Q049=":443"; ma=2592000,h3-Q048=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000

Upvotes: 1

Views: 1816

Answers (1)

aryeh
aryeh

Reputation: 41

This solution worked for me:

const response = await fetch(url, {
            method: 'POST', // or 'PUT'
            body: JSON.stringify(data), // data can be `string` or {object}!
            headers: {
                'Content-Type': 'application/json',
                'Accept': 'application/json'
            }
        }).then(res => res.text());

        console.log(response)
    }

where data is a json object and url is the cloud functions url.

This was the cloud function.

def app_run(request):
    # For more information about CORS and CORS preflight requests, see
    # https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request
    # for more information.

    # 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': '*',  # http://localhost:3000',
            'Access-Control-Allow-Methods': 'POST',
            '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 ('return value', 200, headers)

Upvotes: 3

Related Questions