普通函數(shù)入口
處理函數(shù)入口
一個(gè)最簡單的函數(shù)定義如下:
1. `exports.handler = function(event, context, callback) {`
2. `callback(null, 'hello world');`
3. `};`
函數(shù)名
* `exports.handler` 需要與創(chuàng)建函數(shù)時(shí)的 “handler” 字段相對應(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ù)不對它的內(nèi)容進(jìn)行任何解釋比勉,傳遞給函數(shù)的 event 是 `Buffer` 類型幢哨。您在函數(shù)中可以根據(jù)實(shí)際情況對 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)用請求的唯一 id锈锤,您可以把它記錄下來在出現(xiàn)問題的時(shí)候方便調(diào)查。
* **function: **當(dāng)前調(diào)用的函數(shù)的一些基本信息如函數(shù)名 / 函數(shù)入口 / 函數(shù)內(nèi)存 / 超時(shí)時(shí)間。
* **credentials:** 函數(shù)計(jì)算服務(wù)通過扮演您提供的 [服務(wù)角色](https://help.aliyun.com/document_detail/52885.html) 獲得的一組臨時(shí)密鑰,其有效時(shí)間是 15 分鐘。您可以在代碼中使用它去訪問相應(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í)秘鑰訪問 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è)最簡單的 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” 字段相對應(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é)請參考 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 類型默刚,存放來自 HTTP 客戶端的鍵值對。
* `path`:string 類型,為 HTTP URL冠句。
* `queries`:map 類型,存放來自 HTTP URL 中的 query 部分的 key - value 鍵值對, value 的類型可以為字符串或是數(shù)組径缅。
* `method`:string 類型,HTTP 方法购笆。
* `clientIP`:string 類型,client 的 IP 地址娃循。
* `url`:string 類型,request 的 url。
獲取 HTTP body:HTTP 觸發(fā)器中的 request 兼容 HTTP request跷究,沒有提供額外的 body 字段,直接使用 HTTP request 獲取 body艘儒。
1. `// 詳見示例`
2. `var getRawBody = require('raw-body')`
3. `getRawBody(request, function(err, data){`
4. `var body = data`
5. `})`
如果您的請求是 multipart/form-data 請求逾礁,您可以使用 multiparty 庫進(jìn)行處理蚓峦。
> **說明**:Headers key 中包含以下字段會(huì)被忽略掉低滩,因?yàn)?FC 默認(rèn)會(huì)帶以下字段召夹,不支持用戶自定義。同時(shí)以 `x-fc-` 開頭的 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` )
說明:Headers key 中包含以下字段會(huì)被忽略掉监憎,因?yàn)?FC 默認(rèn)會(huì)帶以下字段,不支持用戶自定義婶溯。同時(shí)以
x-fc-
開頭的 key 也會(huì)被忽略掉鲸阔。
> * `connection`
> * `content-length`
> * `content-encoding`
> * `date`
> * `keep-alive`
> * `proxy-authenticate`
> * `server`
> * `trailer`
> * `transfer-encoding`
> * `upgrade`
限制項(xiàng)
Request 限制項(xiàng)
如果超過以下限制,會(huì)拋出 400
狀態(tài)碼和 InvalidArgument
錯(cuò)誤碼
* headers 的大衅:headers 中的所有 key 和 value 的大小不得超過 4 KB褐筛。
* path 大小:包括各個(gè) query params叙身,path 的大小不得超過 4 KB死讹。
* body 大小:HTTP body 的大小不得超過 6 MB曲梗。
Response 限制項(xiàng)
如果超過以下限制赞警,會(huì)拋出 502
狀態(tài)碼和 BadResponse
錯(cuò)誤碼妓忍。
* headers 的大小:headers 中的所有 key 和 value 的大小不得超過 4 KB愧旦。
* body 大惺榔省:HTTP body 的大小不得超過 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. `};`