普通函數(shù)入口
處理函數(shù)入口
一個(gè)最簡(jiǎn)單的函數(shù)定義如下:
1. `exports.handler = function(event, context, callback) {`
2. `callback(null, 'hello world');`
3. `};`
函數(shù)名
* `exports.handler` 需要與創(chuàng)建函數(shù)時(shí)的 “handler” 字段相對(duì)應(yīng):例如創(chuàng)建函數(shù)時(shí)指定的 handler 為`index.handler`,那么函數(shù)計(jì)算會(huì)去加載 `index.js` 文件中定義的 `handler` 函數(shù)。
event 參數(shù)
* event 參數(shù)是您調(diào)用函數(shù)時(shí)傳入的數(shù)據(jù),其類型是 `Buffer`,是函數(shù)的輸入?yún)?shù)。
* 函數(shù)不對(duì)它的內(nèi)容進(jìn)行任何解釋,傳遞給函數(shù)的 event 是 `Buffer` 類型。您在函數(shù)中可以根據(jù)實(shí)際情況對(duì) event 進(jìn)行轉(zhuǎn)換:例如輸入數(shù)據(jù)是一個(gè) JSON string ,您可以把它轉(zhuǎn)換成一個(gè) `object` :例如:傳入的 event :
1. `{`
2. `"key": "value"`
3. `}`
函數(shù)代碼:
1. `exports.handler = function(event, context, callback) {`
2. `var eventObj = JSON.parse(event.toString());`
3. `callback(null, eventObj['key']);`
4. `};`
返回結(jié)果為 value 。
context 參數(shù)
- context 參數(shù)中包含一些函數(shù)的運(yùn)行時(shí)信息(例如 request id / 臨時(shí) AK 等)。您在代碼中可以使用這些信息。其類型是
object - 其定義如下:
1. `{`
2. `'requestId': 'b1c5100f-819d-c421-3a5e-7782a27d8a33',`
3. `'credentials': {`
4. `'accessKeyId': 'STS.access_key_id',`
5. `'accessKeySecret': 'access_key_secret',`
6. `'securityToken': 'security_token',`
7. `},`
8. `'function': {`
9. `'name': 'my-func',`
10. `'handler': 'index.handler',`
11. `'memory': 128,`
12. `'timeout': 10,`
13. `'initializer': 'index.initializer',`
14. `'initializationTimeout': 10,`
15. `},`
16. `'service': {`
17. `'name': 'my-service',`
18. `'logProject': 'my-log-project',`
19. `'logStore': 'my-log-store',`
20. `},`
21. `'region': 'cn-shanghai',`
22. `'accountId': '123456'`
23. `}`
可以看到 context 中包含了 6 個(gè)信息:
* **requestId: **本次調(diào)用請(qǐng)求的唯一 id,您可以把它記錄下來(lái)在出現(xiàn)問(wèn)題的時(shí)候方便調(diào)查。
* **function: **當(dāng)前調(diào)用的函數(shù)的一些基本信息如函數(shù)名 / 函數(shù)入口 / 函數(shù)內(nèi)存 / 超時(shí)時(shí)間。
* **credentials:** 函數(shù)計(jì)算服務(wù)通過(guò)扮演您提供的 [服務(wù)角色](https://help.aliyun.com/document_detail/52885.html) 獲得的一組臨時(shí)密鑰,其有效時(shí)間是 15 分鐘。您可以在代碼中使用它去訪問(wèn)相應(yīng)的服務(wù)( 例如 OSS ),這就避免了您把自己的 AK 信息寫死在函數(shù)代碼里。
* **service: **當(dāng)前調(diào)用的函數(shù)所在的 service 的信息,包括 service 的名字,接入的 SLS 的 logProject 和 logStore 信息。
* **region: **當(dāng)前調(diào)用的函數(shù)所在區(qū)域,如 cn-shanghai。
* **accountId: **當(dāng)前調(diào)用函數(shù)用戶的阿里云 account id。
下面的代碼使用臨時(shí)密鑰,向 OSS 中上傳了一個(gè)文件:
1. `var OSSClient = require('ali-oss').Wrapper;`
3. `exports.handler = function (event, context, callback) {`
4. `console.log(event.toString());`
6. `var ossClient = new OSSClient({`
7. `accessKeyId: context.credentials.accessKeyId,`
8. `accessKeySecret: context.credentials.accessKeySecret,`
9. `stsToken: context.credentials.securityToken,`
10. `region: 'oss-cn-shanghai',`
11. `bucket: 'my-bucket',`
12. `});`
14. `ossClient.put('my-object', new Buffer('hello, fc')).then(function (res) {`
15. `callback(null, 'put object');`
16. `}).catch(function (err) {`
17. `callback(err);`
18. `});`
19. `};`
注意:使用臨時(shí)秘鑰訪問(wèn) OSS 時(shí)一定要帶上第三個(gè)參數(shù) securityToken。
callback 參數(shù)
- callback 參數(shù)用于返回調(diào)用函數(shù)的結(jié)果,其簽名是
function(err, data),與 Nodejs 中慣用的 callback 一樣,它的第一個(gè)參數(shù)是 error ,第二個(gè)參數(shù) data 。如果調(diào)用時(shí) err 不為空,則函數(shù)將返回HandledInvocationError,否則將返回 data 的內(nèi)容。如果 data 是Buffer類型則它的數(shù)據(jù)將直接被返回,如果 data 是object,則會(huì)將其轉(zhuǎn)換成 JSON 字符串返回,其他類型將被轉(zhuǎn)換成 string 返回。
initializer 入口
一個(gè)最簡(jiǎn)單的 initializer 函數(shù)定義如下:
1. `exports.my_initializer = function(context, callback) {`
2. `console.log('hello world');`
3. `callback(null, "");`
4. `};`
initializer 函數(shù)名
-
my_initializer需要與添加初始化函數(shù)時(shí)的 “initializer” 字段相對(duì)應(yīng):例如創(chuàng)建函數(shù)時(shí)指定的 initializer 為main.my_initializer,那么函數(shù)計(jì)算在配置初始化函數(shù)后首先會(huì)去加載main.js中定義的my_initializer函數(shù)。
initializer 特點(diǎn)
- initializer 輸入?yún)?shù)有 context 和 callback 兩個(gè),具體含義和上文描述的處理函數(shù)中相關(guān)參數(shù)的含義是一致的。
- context 中
initializer和initializationTimeout兩個(gè)信息是為 initializer 設(shè)計(jì)的,當(dāng)使用 initializer 功能時(shí),會(huì)被設(shè)置為用戶創(chuàng)建函數(shù)時(shí)所設(shè)置的值,否則為空,且不生效。
更多細(xì)節(jié)請(qǐng)參考 initializer 入口定義。
設(shè)置 HTTP 觸發(fā)器的函數(shù)入口
注意:設(shè)置了 HTTP 觸發(fā)器的函數(shù)入口與普通函數(shù)的入口不同
1. `function(request, response, context)`
其中的 context 參數(shù)與普通函數(shù)接口的 context 接口相同。
Request 結(jié)構(gòu)體
* `headers`:map 類型,存放來(lái)自 HTTP 客戶端的鍵值對(duì)。
* `path`:string 類型,為 HTTP URL。
* `queries`:map 類型,存放來(lái)自 HTTP URL 中的 query 部分的 key - value 鍵值對(duì), value 的類型可以為字符串或是數(shù)組。
* `method`:string 類型,HTTP 方法。
* `clientIP`:string 類型,client 的 IP 地址。
* `url`:string 類型,request 的 url。
獲取 HTTP body:HTTP 觸發(fā)器中的 request 兼容 HTTP request,沒(méi)有提供額外的 body 字段,直接使用 HTTP request 獲取 body。
1. `// 詳見(jiàn)示例`
2. `var getRawBody = require('raw-body')`
3. `getRawBody(request, function(err, data){`
4. `var body = data`
5. `})`
如果您的請(qǐng)求是 multipart/form-data 請(qǐng)求,您可以使用 multiparty 庫(kù)進(jìn)行處理。
> **說(shuō)明**:Headers key 中包含以下字段會(huì)被忽略掉,因?yàn)?FC 默認(rèn)會(huì)帶以下字段,不支持用戶自定義。同時(shí)以 `x-fc-` 開(kāi)頭的 key 也會(huì)被忽略掉。
>
> * `accept-encoding`
> * `connection`
> * `keep-alive`
> * `proxy-authorization`
> * `te`
> * `trailer`
> * `transfer-encoding`
Response 提供的方法
* `response.setStatusCode(statusCode)` : 設(shè)置 status code
* param `statusCode` : (required, type integer)
* `response.setHeader(headerKey, headerValue)` :設(shè)置 header
* param`headerKey` : (required, type string)
* param`headerValue` : (required, type string)
* `response.deleteHeader(headerKey)` :刪除 header
* param`headerKey`: (required, type string)
* `response.send(body)`: 發(fā)送 body
* param`body`: (required, type`Buffer` or a `string` or a `stream.Readable` )
說(shuō)明:Headers key 中包含以下字段會(huì)被忽略掉,因?yàn)?FC 默認(rèn)會(huì)帶以下字段,不支持用戶自定義。同時(shí)以
x-fc-開(kāi)頭的 key 也會(huì)被忽略掉。
> * `connection`
> * `content-length`
> * `content-encoding`
> * `date`
> * `keep-alive`
> * `proxy-authenticate`
> * `server`
> * `trailer`
> * `transfer-encoding`
> * `upgrade`
限制項(xiàng)
Request 限制項(xiàng)
如果超過(guò)以下限制,會(huì)拋出 400 狀態(tài)碼和 InvalidArgument 錯(cuò)誤碼
* headers 的大?。篽eaders 中的所有 key 和 value 的大小不得超過(guò) 4 KB。
* path 大?。喊ǜ鱾€(gè) query params,path 的大小不得超過(guò) 4 KB。
* body 大?。篐TTP body 的大小不得超過(guò) 6 MB。
Response 限制項(xiàng)
如果超過(guò)以下限制,會(huì)拋出 502 狀態(tài)碼和 BadResponse 錯(cuò)誤碼。
* headers 的大小:headers 中的所有 key 和 value 的大小不得超過(guò) 4 KB。
* body 大?。篐TTP body 的大小不得超過(guò) 6 MB。
示例
示例代碼中展示了如何在函數(shù)中獲取 request 詳細(xì)信息。
1. `var getRawBody = require('raw-body')`
2. `module.exports.handler = function (request, response, context) {`
3. `// get requset header`
4. `var reqHeader = request.headers`
5. `var headerStr = ' '`
6. `for (var key in reqHeader) {`
7. `headerStr += key + ':' + reqHeader[key] + ' '`
8. `};`
10. `// get request info`
11. `var url = request.url`
12. `var path = request.path`
13. `var queries = request.queries`
14. `var queryStr = ''`
15. `for (var param in queries) {`
16. `queryStr += param + "=" + queries[param] + ' '`
17. `};`
18. `var method = request.method`
19. `var clientIP = request.clientIP`
21. `// get request body`
22. `getRawBody(request, function (err, data) {`
23. `var body = data`
24. `// you can deal with your own logic here`
26. `// set response`
27. `// var respBody = new Buffer('requestURI' + requestURI + ' path' + path + ' method' + method + ' clientIP' + clientIP)`
28. `var respBody = new Buffer('requestHeader:' + headerStr + '\n' + 'url: ' + url + '\n' + 'path: ' + path + '\n' + 'queries: ' + queryStr + '\n' + 'method: ' + method + '\n' + 'clientIP: ' + clientIP + '\n' + 'body: ' + body + '\n')`
29. `// var respBody = new Buffer( )`
30. `response.setStatusCode(200)`
31. `response.setHeader('content-type', 'application/json')`
33. `response.send(respBody)`
35. `})`
36. `};`