前言
云函数可以让业务部署更快速更轻松,对于我来说,部署API非常方便,在以前API网关就担任了HTTP触发器的功能,不过在今年7月,API网关宣布了下架的消息,转而使用TSE云原生网关,不过对于我们业务量不大的用户来说,TSE的价格实在承担不起,而且很多功能也用不上
我们使用API网关的场景也就是路径,自定义域名,透传body,header,query等http参数,以及自定义验证等等功能,实际上,这些可以直接在业务函数里面集成。
函数本身自带一个触发URL,更多的还是纯为API设计的,因为不支持浏览器预览,而且唯一的作用就是触发函数仅此而已。
踩坑
函数的内容仅仅是返回event对象
代码语言:js复制exports.main_handler =async (event, context) => {
return event;
}
使用APIFox,能够正常返回响应
代码语言:json复制{
"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-Headers
,Access-Control-Allow-Methods
,Access-Control-Allow-Origin
等。
所以要能让浏览器正常请求,就需要函数返回能够让浏览器通过CORS检查的响应头。
云函数侧解决
云函数部分可以通过返回类似下图结构的内容,实现自定义参数的设置。
主要关注header部分
在返回时,带上这几个header,即可让浏览器通过CORS
这是一个示例,例如我想从https://a.com
和https://b.com
,给我的函数URL发送带有请求头token
的,支持POST、PUT、GET的请求
......
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函数如下:
代码语言:js复制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
- [1] 跨源资源共享(CORS) https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS
- [2] 云函数URL概述 https://cloud.tencent.com/document/product/583/96099