【发布时间】:2020-10-15 13:42:17
【问题描述】:
我使用 Google Cloud Functions 创建了一个 API 端点,并试图从 JS 提取函数中调用它。
我遇到了我很确定与 CORS 或输出格式有关的错误,但我不确定发生了什么。其他一些 SO 问题类似,并帮助我意识到我需要删除 mode: "no-cors"。大多数人提到在 BE 上启用 CORS,所以我添加了 response.headers.set('Access-Control-Allow-Origin', '*') - 我在 this article 中了解到的 - 以确保启用 CORS...但我仍然收到“无法获取”错误。
完整错误(可在下面链接的现场演示中重现)是:
未捕获的错误:无法添加节点 1,因为具有该 ID 的节点是 已经在商店中。 (这可能是无关的?)
访问获取 'https://us-central1-stargazr-ncc-2893.cloudfunctions.net/nearest_csc?lat=37.75&lon=-122.5' 来自原点“https://o2gxx.csb.app”已被 CORS 政策阻止: 请求头字段 access-control-allow-origin 不允许 预检响应中的 Access-Control-Allow-Headers。
获取 https://us-central1-stargazr-ncc-2893.cloudfunctions.net/nearest_csc?lat=37.75&lon=-122.5net::ERR_FAILED
Uncaught (in promise) TypeError: Failed to fetch
请参阅下面的代码片段,请注意我在哪里使用 <---- *** Message *** 来表示最近更改的代码部分,这给了我这两个错误之一。
前端代码:
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());
});
}
后端代码:
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"
以上代码 sn-ps 的更完整上下文:
- 这是上面的Code Sandbox Demo。
- 这是full BE code on GitHub,减去最近添加 CORS 的尝试。
- API endpoint。
我还想知道 CodeSandbox 是否有可能以一种奇怪的方式执行 CORS,但在 localhost:3000 上运行它时遇到了同样的问题,当然在 prod 中会在我自己的个人域上遇到这个问题。
该错误似乎与 CORS 相关 ( '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.),但我认为添加 response.headers.set('Access-Control-Allow-Origin', '*') 可以解决该问题。我需要在 BE 上更改其他内容吗?在 FE 上?
TLDR;
即使在尝试在后端启用 CORS 并将标头添加到 FE 之后,我也收到错误“无法获取”和“Access-Control-Allow-Headers 不允许字段访问控制允许来源”。有关代码的实时演示,请参见上面的链接。
【问题讨论】:
-
不要尝试在前端 JavaScript 代码中添加 access-control-allow-origin 作为请求标头。也不要尝试添加 Origin 标头。浏览器不允许您进行设置。因此,需要从前端 fetch 调用中删除整个
headers块,然后重试 - 然后更新问题,详细说明删除headers块后会发生什么。 -
似乎从 FE 中删除“ Origin: "lget3.csb.app", "Access-Control-Allow-Origin": "*"" 有效!谢谢。
-
我仍然对它为什么起作用以及之前的问题有点困惑。 FE 现在与我开始查找如何解决 CORS 错误之前相同。但我也更改了 BE,所以也许这就是所有需要的?如果您想写一个答案来解释为什么我不需要 FE 上的标题(正如许多其他答案所暗示的那样)以及 BE 上需要什么,我很乐意接受!
-
好的,终于有时间写一个实际的答案了。
-
请注意,我还冒昧地更新了问题标题——我这样做是为了概括对根本问题的描述,以便将来遇到相同问题的读者/搜索者可以找到解决方案/答案在这里更容易,无论他们可能使用何种特定的前端和后端框架/库/运行时组合(因为该解决方案与任何特定的技术选择无关。)
标签: javascript python cors