本文档描述了 如何使用云函数处理HTTP请求,即 HTTP请求如何转换为云函数的入参,云函数的返回值如何转换为HTTP响应。
云函数代码
以下为一个简单的云函数代码片段:
exports.main = async (event, context) => {console.log('event: ', event)console.log('context: ', context)return { event, context }}
这段代码并没有 HTTP服务相关的内容,并不会启动一个监听某端口的 HTTP 服务。那么就出现了一个问题:这个云函数怎么接收 HTTP 请求,怎么返回 HTTP 响应。本篇文档将详细解答这个问题。
云函数的入参
通过 HTTP 调用云函数时,HTTP 请求会被转化为称之为集成请求的特殊的结构体,并通过云函数入参 event 传递给云函数入口函数。
集成请求,就是通过 JSON 格式数据描述 HTTP 响应报文的一段数据。
集成请求结构如下:
{"path": "HTTP请求路径,如 /hello","httpMethod": "HTTP请求方法,如 GET","headers": {}, // HTTP请求头,key:value,value 为字符串"multiValueHeaders": {} // HTTP请求头,key:value,value 为字符串数组,用于支持存在相同请求头的情形"queryStringParameters": {}, // HTTP请求的Query,键值对形式"requestContext": {}, // 云开发相关信息"body": "HTTP请求体", // 普通文本 或 Base64 编码,如果是 isBase64Encoded=true,则是 Base64 编码"isBase64Encoded": false // true or false,表示 body 是否为 Base64 编码,如果是 Base64 编码,业务需要解码后获得元数据。如果 HTTP 请求包体是 二进制数据,则包体内容会被处理成 Base64编码的字符串,此时该值为 true。}
下面是该结构的一个示例:
{"path": "/","httpMethod": "GET","headers": {"host": "env-id.service.tcloudbase.com","connection": "close","user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"},"multiValueHeaders": {"host": ["env-id.service.tcloudbase.com"],"connection": ["close"],"user-agent": ["Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"]},"queryStringParameters": {},"isBase64Encoded": false,"body": ""}
云函数的返回值
集成响应,就是通过 JSON 格式数据描述 HTTP 响应报文的一段内容。
返回字符串或数字
云函数返回字符串或数字,字符串将会被放在 HTTP 响应 Body 中返回,同时 HTTP 响应的
content-type
会被设置为 text/plain
。module.exports.main = async function () {return "hello gateway"}
最终 HTTP 响应为:
HTTP/1.1 200 OKdate: Mon, 16 Dec 2019 08:35:31 GMTcontent-type: text/plain; charset=utf-8content-length: 13hello gateway
返回 Object
云函数返回的 JS 对象会被转换为 JSON 字符串并在 HTTP 响应 Body 中返回,同时 HTTP 响应的
content-type
会被设置为 application/json
。module.exports.main = async function () {return {foo: "bar"}}
最终 HTTP 响应为:
HTTP/1.1 200 OKdate: Mon, 16 Dec 2019 08:35:31 GMTcontent-type: application/json; charset=utf-8content-length: 13{"foo":"bar"}
返回集成响应
云函数可以返回如下这样特殊结构的集成响应,来自由地控制响应体。
{"statusCode": 200, // HTTP状态码"headers": { "headerName": "headerValue", ... }, // HTTP 响应头"body": "...", // HTTP 响应体,如果需返回 二进制数据,可以将二进制数据编码成 Base64字符串,并将 isBase64Encoded 设置为 true"isBase64Encoded": false, // HTTP 响应体是否是 Base64 编码}
使用集成响应返回 HTML
将
content-type
设置为 text/html
,即可在 body
中返回 HTML,会被浏览器自动解析:module.exports.main = async function () {return {statusCode: 200,headers: {"content-type": "text/html"},body: "<h1>Hello</h1>"}}
最终 HTTP 响应为:
HTTP/1.1 200 OKdate: Mon, 16 Dec 2019 08:35:31 GMTcontent-type: text/html; charset=utf-8content-length: 14<h1>Hello</h1>
使用集成响应返回 JS 文件
将
content-type
设置为 application/javascript
,即可在 body
中返回 JavaScript 文件:module.exports.main = async function () {return {statusCode: 200,headers: {"content-type": "application/javascript"},body: 'console.log("Hello!")'}}
最终 HTTP 响应为:
HTTP/1.1 200 OKdate: Mon, 16 Dec 2019 08:35:31 GMTcontent-type: application/javascript; charset=utf-8content-length: 21console.log("Hello!")
使用集成响应返回二进制文件
如果返回体是诸如图片、音视频这样的二进制文件,那么可以将
isBase64Encoded
设置为 true
,并且将二进制文件内容转为 Base64 编码的字符串,例如:module.exports.main = async function () {return {isBase64Encoded: true,statusCode: 200,headers: {"content-type": "image/png"},body: "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAY..."}}
最终 HTTP 响应为一张 PNG 图片:
HTTP/1.1 200 OKdate: Mon, 16 Dec 2019 08:35:31 GMTcontent-type: image/pngcontent-length: 9897<binary payload...>