【云函数SCF】浏览器请求函数URL,实现CORS

本文最后更新于:2024年9月23日 下午

前言

云函数可以让业务部署更快速更轻松,对于我来说,部署API非常方便,在以前API网关就担任了HTTP触发器的功能,不过在今年7月,API网关宣布了下架的消息,转而使用TSE云原生网关,不过对于我们业务量不大的用户来说,TSE的价格实在承担不起,而且很多功能也用不上

我们使用API网关的场景也就是路径,自定义域名,透传body,header,query等http参数,以及自定义验证等等功能,实际上,这些可以直接在业务函数里面集成。

函数本身自带一个触发URL,更多的还是纯为API设计的,因为不支持浏览器预览,而且唯一的作用就是触发函数仅此而已。

踩坑

函数的内容仅仅是返回event对象

1
2
3
exports.main_handler =async (event, context) => {
return event;
}

使用APIFox,能够正常返回响应

请在此添加图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
"body": "",
"headers": {
"accept": "*/*",
"accept-encoding": "gzip, deflate, br",
"connection": "keep-alive",
"token": "xxxxxxxxx",
"user-agent": "Apifox/1.0.0 (https://apifox.com)",
"x-scf-request-id": "52a7f5b2-xxxxxxx-xxxx-xxxxxxxx-525400df965c"
},
"httpMethod": "GET",
"path": "/",
"queryString": {}
}

但当使用浏览器发起fetch/XHR时,就出现错误了:

Access to fetch xxxxxxxxxxxxx from origin ‘http://127.0.0.1:3000" has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: NoAccess-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.

请在此添加图片描述

意思就是浏览器被CORS拦了

问题和解决

产生的原因

具体产生的原因可以参考:跨源资源共享(CORS)【秒杀】前端网络-CORS

简言之,浏览器判断CORS能否通过,就靠那几个靠响应头,简单请求时看Access-Control-Allow-Origin是否存在发送请求时的域,非简单请求时检查Access-Control-Allow-HeadersAccess-Control-Allow-MethodsAccess-Control-Allow-Origin等。

所以要能让浏览器正常请求,就需要函数返回能够让浏览器通过CORS检查的响应头。

云函数侧解决

云函数部分可以通过返回类似下图结构的内容,实现自定义参数的设置。

主要关注header部分

请在此添加图片描述

在返回时,带上这几个header,即可让浏览器通过CORS

这是一个示例,例如我想从https://a.comhttps://b.com,给我的函数URL发送带有请求头token的,支持POST、PUT、GET的请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
......
return {
"statusCode": 200,
"headers": {
"Content-Type": "application/json",
// CORS所需响应头
"Access-Control-Allow-Origin": "https://a.com,https://b.com",
"Access-Control-Allow-Methods": "POST,PUT,GET",
"Access-Control-Allow-Headers": "token",
// 其他需要响应回去的头
"My-Header": "MyValue"
},
"body": JSON.stringify({
"message": "Hello, world!"
})
}

整个event函数如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
exports.main_handler = async (event, context) => {
return {
"statusCode": 200,
"headers": {
"Content-Type": "application/json",
// CORS所需响应头
"Access-Control-Allow-Origin": "https://a.com,https://b.com",
"Access-Control-Allow-Methods": "POST,PUT,GET",
"Access-Control-Allow-Headers": "token",
// 其他需要响应回去的头
"My-Header": "MyValue"
},
"body": JSON.stringify({
message: "Hello World"
})
}
}

这时,从浏览器侧调用fetch/XHR云函数的URL,就可以正常访问了

请在此添加图片描述

关于响应头更多设置,可参考HTTP 响应标头字段(MDN)

归纳总结

出现浏览器CORS报错的问题,十有八九是因为响应头出问题了,如果你是前端,看看发送的参数有没有问题,是否遵循公司内接口文档的规范;如果你是后端,看看给回去的响应头有没有给前端配置对应的CORS头。

Reference


【云函数SCF】浏览器请求函数URL,实现CORS
https://www.arirs.cn/posts/2448677/
作者
Ar-Sr-Na
发布于
2024年8月31日
许可协议