I created an API endpoint using Google Cloud Functions and am trying to call it from a JS fetch function.
I am running into errors that I am pretty sure are related to either CORS or the output format, but I'm not really sure what is going on. A few other SO questions are similar, and helped me realize I needed to remove the mode: "no-cors". Most mention enabling CORS on the BE, so I added response.headers.set('Access-Control-Allow-Origin', '*') - which I learned of in this article - to ensure CORS would be enabled... But I still get the "Failed to fetch" error.
The Full Errors (reproducible in the live demo linked below) are:
Uncaught Error: Cannot add node 1 because a node with that id is already in the Store. (This one is probably unrelated?)
Access to fetch at 'https://us-central1-stargazr-ncc-2893.cloudfunctions.net/nearest_csc?lat=37.75&lon=-122.5' from origin 'https://o2gxx.csb.app' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.
GET https://us-central1-stargazr-ncc-2893.cloudfunctions.net/nearest_csc?lat=37.75&lon=-122.5 net::ERR_FAILED
Uncaught (in promise) TypeError: Failed to fetch
See Code Snippets below, please note where I used <---- *** Message *** to denote parts of the code that have recently changed, giving me one of those two errors.
Front End Code:
function getCSC() {
let lat = 37.75;
let lng = -122.5;
fetch(
`https://us-central1-stargazr-ncc-2893.cloudfunctions.net/nearest_csc?lat=${lat}&lon=${lng}`,
{
method: "GET",
// mode: "no-cors", <---- **Uncommenting this predictably gets rid of CORS error but returns a Opaque object which seems to have no data**
headers: {
// Accept: "application/json", <---- **Originally BE returned stringified json. Not sure if I should be returning it as something else or if this is still needed**
Origin: "https://lget3.csb.app",
"Access-Control-Allow-Origin": "*"
}
}
)
.then(response => {
console.log(response);
console.log(response.json());
});
}
Back End Code:
import json
import math
import os
import flask
def nearest_csc(request):
"""
args: request object w/ args for lat/lon
returns: String, either with json representation of nearest site information or an error message
"""
lat = request.args.get('lat', type = float)
lon = request.args.get('lon', type = float)
# Get list of all csc site locations
with open(file_path, 'r') as f:
data = json.load(f)
nearby_csc = []
# Removed from snippet for clarity:
# populate nearby_csc (list) with sites (dictionaries) as elems
# Determine which site is the closest, assigned to var 'closest_site'
# Grab site url and return site data if within 100 km
if dist_km < 100:
closest_site['dist_km'] = dist_km
// return json.dumps(closest_site) <--- **Original return statement. Added 4 lines below in an attempt to get CORS set up, but did not seem to work**
response = flask.jsonify(closest_site)
response.headers.set('Access-Control-Allow-Origin', '*')
response.headers.set('Access-Control-Allow-Methods', 'GET, POST')
return response
return "No sites found within 100 km"
Fuller context for code snippets above:
- Here is a Code Sandbox Demo of the above.
- Here is the full BE code on GitHub, minus the most recent attempt at adding CORS.
- The API endpoint.
I'm also wondering if it's possible that CodeSandbox does CORS in a weird way, but have had the same issue running it on localhost:3000, and of course in prod would have this on my own personal domain.
The Error would appear to be CORS-related ( 'https://o2gxx.csb.app' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.) but I thought adding response.headers.set('Access-Control-Allow-Origin', '*') would solve that. Do I need to change something else on the BE? On the FE?
TLDR;
I am getting the Errors "Failed to fetch" and "field access-control-allow-origin is not allowed by Access-Control-Allow-Headers" even after attempts to enable CORS on backend and add headers to FE. See the links above for live demo of code.