函數計算是一個事件驅動的服務,將API網關與函數計算服務對接后,即可通過API形式安全地對外開放函數,并且解決認證、流量控制、數據轉換等問題。本文以函數計算3.0為例介紹如何對接API網關與函數計算服務。
前提條件
功能簡介
API網關目前支持兩種形式的函數計算服務,HTTP函數和事件函數。
HTTP函數對接API網關
創建Web函數
在配置API網關前,需要先在函數計算3.0控制臺中創建一個Web函數。可參考創建Web函數。
創建后端服務
在API網關中定義后端服務,并配置后端服務地址來對接函數計算服務。
登錄API網關控制臺,左側導航欄選擇API管理 > 后端服務,在頂部菜單欄選擇地域,單擊創建后端服務。
在創建后端服務彈框中,按圖所示填寫配置信息,并單擊確定。
在后端服務頁面,單擊剛剛創建的后端服務,進入后端服務定義頁,選擇線上頁簽,在基本信息處單擊創建。
在創建的基本信息頁面,配置觸發器路徑的訪問地址,單擊發布。
創建API
在API網關控制臺上創建API,詳情可參見創建API。
API分組。建議API分組與函數計算在相同的地域。
如果函數計算與 API 不在同一地域,將通過公網訪問您的函數計算服務,產生流量費用。若您對數據安全和網絡延遲有較高要求,請選擇API與函數計算為同一地域。
創建和定義API。在“定義API后端服務”步驟中,如下圖所示:
后端配置:使用已有的后端服務
后端服務類型:函數計算
產品版本:函數計算3.0
函數類型:HTTP函數
后端服務:選擇已創建的后端服務名。
后端請求path:可以自定義path,如果不需要自定義,請填寫“/”。
HTTP Method:請選擇后端函數計算支持的method, 如果多個請選擇“ANY”。
使用其他賬號的函數計算
API網關除了使用相同賬號下的函數計算服務外,還可以使用其他賬號下的函數計算服務。以A賬號下的API網關需要使用B賬號下的函數計算為例,介紹如何操作。
B賬號為A賬號API網關的訪問函數計算授權。
步驟1:使用B賬號登錄RAM控制臺,創建RAM角色,參考創建可信實體為阿里云賬號的RAM角色。
步驟2:為步驟1中創建的角色增加調用函數計算的授權。需要添加名為AliyunFCInvocationAccess的系統權限,參考在RAM角色管理頁面為RAM角色授權。
步驟3:修改步驟1創建的角色的信任策略,參考 修改RAM角色的可信實體為阿里云賬號。將A賬號的AccountID(如123456789012****)添加到信任策略中,修改后的信任策略如下:
{ "Statement": [ { "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { "Service": [ "123456789012****@apigateway.aliyuncs.com" ] } } ], "Version": "1" }
步驟4:B賬號將步驟1創建的角色的Arn(了解 RAM角色基本概念)提供給A賬號。
A賬號在API網關控制臺中添加訪問B賬號的函數計算服務。其中觸發路徑內容為B賬號下的函數計算服務的訪問地址,角色Arn中填寫B賬號提供的角色Arn名稱。
當后端服務為HTTP函數時,客戶端發送的Authorization參數值會被HTTP函數的Authorization覆蓋,建議客戶端更換參數名稱。
事件函數對接API網關
創建事件觸發函數
在函數計算3.0控制臺創建事件函數可參見創建事件函數。
創建后端服務
在API網關中定義后端服務,并配置后端服務地址來對接函數計算服務。
登錄API網關控制臺,選擇地域并在左側導航欄選擇API管理 > 后端服務,單擊右上角創建后端服務,配置如下信息,單擊確定。
在后端服務頁面,單擊剛剛創建的后端服務,進入后端服務定義頁,選擇線上頁簽,在基本信息處單擊創建。
選擇函數名稱為所創建的事件函數,單擊發布。
創建API
在API網關控制臺上創建API,詳情可參見創建API。
API分組。建議API分組與函數計算在相同的地域。
如果函數計算與 API 不在同一地域,將通過公網訪問您的函數計算服務,產生流量費用。若您對數據安全和網絡延遲有較高要求,請選擇API 與函數計算為同一地域。
創建API。在“定義API后端服務”步驟中,如下圖所示:
后端配置:使用已有的后端服務
后端服務類型:函數計算
產品版本:函數計算3.0
函數類型:事件函數
后端服務:選擇已創建的后端服務名。
事件函數對接API網關的格式要求
API 網關調用函數計算的事件函數時,會將 API 的相關數據轉換為 Map 形式傳給函數計算服務。函數計算服務處理后,按照下圖中 Output Format 的格式返回 statusCode、headers、body 等相關數據。API 網關再將函數計算返回的內容映射到 statusCode、header、body等位置返回給客戶端。
API 網關向函數計算傳入參數格式:
當以函數計算作為 API 網關的后端服務時,API 網關會把請求參數通過一個固定的 Map 結構傳給函數計算的入參 event。函數計算通過如下結構去獲取需要的參數,然后進行處理。
{
"path":"api request path",
"httpMethod":"request method name",
"headers":{all headers,including system headers},
"queryParameters":{query parameters},
"pathParameters":{path parameters},
"body":"string of request payload",
"isBase64Encoded":"true|false, indicate if the body is Base64-encode"
}
如果
"isBase64Encoded"
的值為"true"
,表示 API 網關傳給函數計算的 body 內容已進行 Base64 編碼。函數計算需要先對 body 內容進行 Base64 解碼后再處理。如果
"isBase64Encoded"
的值為"false"
,表示 API 網關沒有對 body 內容進行 Base64 編碼。
函數計算的返回參數格式:
函數計算需要將輸出內容通過如下 JSON 格式返回給 API 網關,以便 API 網關解析。
{
"isBase64Encoded":true|false,
"statusCode":httpStatusCode,
"headers":{response headers},
"body":"..."
}
當 body 內容為二進制編碼時,需在函數計算中對 body 內容進行 Base64 編碼,設置
"isBase64Encoded"
的值為"true"
。如果 body 內容無需 Base64 編碼,"isBase64Encoded"
的值為"false"
。API 網關會對"isBase64Encoded"
的值為"true"
的 body 內容進行 Base64 解碼后,再返回給客戶端。在 Node.js 環境中,函數計算根據不同的情況設置 callback。
返回成功請求: callback(null,{"statusCode":200,"body":"..."})。
返回異常:callback(new Error('internal server error'),null)。
返回客戶端錯誤: callback(null,{"statusCode":400,"body":"param error"})。
如果函數計算返回不符合格式要求的結果,API 網關將返回503 Service Unavailable給客戶端。
事件函數調用示例
以下提供三個示例,分別為:事件函數代碼示例、事件函數請求示例和API網關返回示例。
事件函數代碼示例
在函數計算的代碼執行頁面配置的代碼示例。
module.exports.handler = function(event, context, callback) {
var responseCode = 200;
console.log("request: " + JSON.stringify(event.toString()));
//將event轉化為JSON對象
event=JSON.parse(event.toString());
var isBase64Encoded=false;
//根據用戶輸入的statusCode返回,可用于測試不同statusCode的情況
if (event.queryParameters !== null && event.queryParameters !== undefined) {
if (event.queryParameters.httpStatus !== undefined && event.queryParameters.httpStatus !== null && event.queryParameters.httpStatus !== "") {
console.log("Received http status: " + event.queryParameters.httpStatus);
responseCode = event.queryParameters.httpStatus;
}
}
//如果body是Base64編碼的,FC中需要對body內容進行解碼
if(event.body!==null&&event.body!==undefined){
if(event.isBase64Encoded!==null&&event.isBase64Encoded!==undefined&&event.isBase64Encoded){
event.body=new Buffer(event.body,'base64').toString();
}
}
//input是API網關給FC的輸入內容
var responseBody = {
message: "Hello World!",
input: event
};
//對body內容進行Base64編碼,可根據需要處理
var base64EncodeStr=new Buffer(JSON.stringify(responseBody)).toString('base64');
//FC給API網關返回的格式,須如下所示。isBase64Encoded根據body是否Base64編碼情況設置
var response = {
isBase64Encoded:true,
statusCode: responseCode,
headers: {
"x-custom-header" : "header value"
},
body: base64EncodeStr
};
console.log("response: " + JSON.stringify(response));
callback(null, response);
};
事件函數請求示例
以POST形式請求 path 為如下的 API:
/fc/test/invoke/[type]
發起請求如下:
POST http://test.alicloudapi.com/fc/test/invoke/test?param1=aaa¶m2=bbb
"X-Ca-Signature-Headers":"X-Ca-Timestamp,X-Ca-Version,X-Ca-Key,X-Ca-Stage",
"X-Ca-Signature":"TnoBldxxRHrFferGlzzkGcQsaezK+ZzySloKqCOsv2U=",
"X-Ca-Stage":"RELEASE",
"X-Ca-Timestamp":"1496652763510",
"Content-Type":"application/x-www-form-urlencoded; charset=utf-8",
"X-Ca-Version":"1",
"User-Agent":"Apache-HttpClient\/4.1.2 (java 1.6)",
"Host":"test.alicloudapi.com",
"X-Ca-Key":"testKey",
"Date":"Mon, 05 Jun 2017 08:52:43 GMT","Accept":"application/json",
"headerParam":"testHeader"
{"bodyParam":"testBody"}
API網關返回示例
200
Date: Mon, 05 Jun 2017 08:52:43 GMT
Content-Type: application/json; charset=UTF-8
Content-Length: 429
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,HEAD,OPTIONS , PATCH
Access-Control-Allow-Headers: X-Requested-With, X-Sequence,X-Ca-Key,X-Ca-Secret,X-Ca-Version,X-Ca-Timestamp,X-Ca-Nonce,X-Ca-API-Key,X-Ca-Stage,X-Ca-Client-DeviceId,X-Ca-Client-AppId,X-Ca-Signature,X-Ca-Signature-Headers,X-Forwarded-For,X-Ca-Date,X-Ca-Request-Mode,Authorization,Content-Type,Accept,Accept-Ranges,Cache-Control,Range,Content-MD5
Access-Control-Max-Age: 172800
X-Ca-Request-Id: 16E9D4B5-3A1C-445A-BEF1-4AD8E31434EC
x-custom-header: header value
{"message":"Hello World!","input":{"body":"{\"bodyParam\":\"testBody\"}","headers":{"X-Ca-Api-Gateway":"16E9D4B5-3A1C-445A-BEF1-4AD8E31434EC","headerParam":"testHeader","X-Forwarded-For":"100.81.146.152","Content-Type":"application/x-www-form-urlencoded; charset=UTF-8"},"httpMethod":"POST","isBase64Encoded":false,"path":"/fc/test/invoke/test","pathParameters":{"type":"test"},"queryParameters":{"param1":"aaa","param2":"bbb"}}}
常見問題
為什么我無法錄入我已有的函數?
請確認您輸入的函數計算的服務名稱和函數名稱是否與您在函數計算控制臺創建的服務和函數的名稱一致。
使用函數計算作為API后端服務時,API網關到后端服務是否可以走內網?
當選擇事件函數時,API網關和函數計算在同一region時,默認走內網。