Function Compute是一個事件驅動的服務,將API Gateway與Function Compute服務對接後,即可通過API形式安全地對外開放函數,並且解決認證、流量控制、資料轉換等問題。本文以Function Compute3.0為例介紹如何對接API Gateway與Function Compute服務。
前提條件
已建立API Gateway執行個體,關於執行個體的選型資訊,請參考執行個體類型與選擇指南。
功能簡介
API Gateway目前支援兩種形式的Function Compute服務,HTTP函數和事件函數。
HTTP函數對接API Gateway
1. 建立Web函數
在配置API Gateway前,需要先在Function Compute3.0控制台中建立一個Web函數。可參考建立Web函數。
2. 建立後端服務
在API Gateway中定義後端服務,並配置後端服務地址來對接Function Compute服務。
登入API Gateway控制台,左側導覽列選擇,在頂部功能表列選擇地區,單擊建立後端服務。

在建立後端服務彈框中,按圖所示填寫配置資訊,並單擊確定。

在後端服務頁面,單擊剛剛建立的後端服務,進入後端服務定義頁,選擇線上頁簽,在基本資料處單擊建立。

在建立的基本資料頁面,配置觸發器路徑的訪問地址,單擊發布。

3. 建立API
在API Gateway控制台上建立API,詳情可參見建立API。
API分組。建議API分組與Function Compute在相同的地區。
如果Function Compute與 API 不在同一地區,將通過公網訪問您的Function Compute服務,產生流量費用。若您對資料安全和網路延遲有較高要求,請選擇API與Function Compute為同一地區。
建立和定義API。在“定義API後端服務”步驟中,如下圖所示:

後端配置:使用已有的後端服務。
後端服務類型:Function Compute。
產品版本:Function Compute3.0。
函數類型:HTTP函數。
後端服務:選擇已建立的後端服務名。
後端請求path:可以自訂path,如果不需要自訂,請填寫“/”。
HTTP Method:請選擇後端Function Compute支援的method,如果多個請選擇“ANY”。
使用其他帳號的Function Compute
API Gateway除了使用相同帳號下的Function Compute服務外,還可以使用其他帳號下的Function Compute服務。以A帳號下的API Gateway需要使用B帳號下的Function Compute為例,介紹如何操作。
B帳號為A帳號API Gateway的訪問Function Compute授權。
步驟1:使用B帳號登入RAM控制台,建立RAM角色,參考建立可信實體為阿里雲帳號的RAM角色。
步驟2:為步驟1中建立的角色增加調用Function Compute的授權。需要添加名為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 Gateway控制台中添加訪問B帳號的Function Compute服務。其中觸發路徑內容為B帳號下的Function Compute服務的訪問地址,角色Arn中填寫B帳號提供的角色Arn名稱。
當後端服務為HTTP函數時,用戶端發送的Authorization參數值會被HTTP函數的Authorization覆蓋,建議用戶端更換參數名稱。
事件函數對接API Gateway
1. 建立事件觸發函數
在Function Compute3.0控制台建立事件函數可參見建立事件函數。
2. 建立後端服務
在API Gateway中定義後端服務,並配置後端服務地址來對接Function Compute服務。
登入API Gateway控制台,選擇地區並在左側導覽列選擇,單擊右上方建立後端服務,配置如下資訊,單擊確定。

在後端服務頁面,單擊剛剛建立的後端服務,進入後端服務定義頁,選擇線上頁簽,在基本資料處單擊建立。

選擇函數名稱為所建立的事件函數,單擊發布。

3. 建立API
在API Gateway控制台上建立API,詳情可參見建立API。
API分組。建議API分組與Function Compute在相同的地區。
如果Function Compute與 API 不在同一地區,將通過公網訪問您的Function Compute服務,產生流量費用。若您對資料安全和網路延遲有較高要求,請選擇API 與Function Compute為同一地區。
建立API。在“定義API後端服務”步驟中,如下圖所示:

後端配置:使用已有的後端服務。
後端服務類型:Function Compute。
產品版本:Function Compute3.0。
函數類型:事件函數。
後端服務:選擇已建立的後端服務名。
事件函數對接API Gateway的格式要求
API Gateway調用Function Compute的事件函數時,會將 API 的相關資料轉換為 Map 形式傳給Function Compute服務。Function Compute服務處理後,按照下圖中 Output Format 的格式返回 statusCode、headers、body 等相關資料。API Gateway再將Function Compute返回的內容映射到 statusCode、header、body等位置返回給用戶端。

API Gateway向Function Compute傳入參數格式:
當以Function Compute作為 API Gateway的後端服務時,API Gateway會把請求參數通過一個固定的 Map 結構傳給Function Compute的入參 event。Function Compute通過如下結構去擷取需要的參數,然後進行處理。
{
"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 Gateway傳給Function Compute的 body 內容已進行 Base 64 編碼。Function Compute需要先對 body 內容進行 Base64 解碼後再處理。如果
"isBase64Encoded"的值為"false",表示 API Gateway沒有對 body 內容進行 Base 64 編碼。
Function Compute的返回參數格式:
Function Compute需要將輸出內容通過如下 JSON 格式返回給 API Gateway,以便 API Gateway解析。
{
"isBase64Encoded":true|false,
"statusCode":httpStatusCode,
"headers":{response headers},
"body":"..."
}當 body 內容為二進位編碼時,需在Function Compute中對 body 內容進行 Base 64 編碼,設定
"isBase64Encoded"的值為"true"。如果 body 內容無需 Base 64 編碼,"isBase64Encoded"的值為"false"。API Gateway會對"isBase64Encoded"的值為"true"的 body 內容進行 Base64 解碼後,再返回給用戶端。在 Node.js 環境中,Function Compute根據不同的情況設定 callback。
返回成功請求: callback(null,{"statusCode":200,"body":"..."})。
返回異常:callback(new Error('internal server error'),null)。
返回用戶端錯誤: callback(null,{"statusCode":400,"body":"param error"})。
如果Function Compute返回不符合格式要求的結果,API Gateway將返回503 Service Unavailable給用戶端。
事件函數調用樣本
以下提供三個樣本,分別為:事件函數程式碼範例、事件函數請求樣本和API Gateway返回樣本。
事件函數程式碼範例
在Function Compute的代碼執行頁面配置的程式碼範例。
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 Gateway給FC的輸入內容
var responseBody = {
message: "Hello World!",
input: event
};
//對body內容進行Base64編碼,可根據需要處理
var base64EncodeStr=new Buffer(JSON.stringify(responseBody)).toString('base64');
//FC給API Gateway返回的格式,須如下所示。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 Gateway返回樣本
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"}}}
常見問題
為什麼我無法錄入我已有的函數?
請確認您輸入的Function Compute的服務名稱和函數名稱是否與您在Function Compute控制台建立的服務和函數的名稱一致。
使用Function Compute作為API後端服務時,API Gateway到後端服務是否可以走內網?
當選擇事件函數時,API Gateway和Function Compute在同一region時,預設走內網。