Reputation: 41
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
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