API閘道中的 Lambda 代理整合 - Amazon API Gateway

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

API閘道中的 Lambda 代理整合

以下部分說明如何使用 Lambda 代理整合。

瞭解API閘道 Lambda 代理整合

Amazon API 閘道 Lambda 代理整合是一種簡單、功能強大且靈活的機制,可API透過單一API方法設定來建置。Lambda 代理整合可讓用戶端在後端呼叫單一 Lambda 函數。此函數可存取其他 AWS 服務的許多資源或功能,包括呼叫其他 Lambda 函數。

在 Lambda 代理整合中,當用戶端提交API請求時,API閘道會將事件物件傳遞給整合的 Lambda 函數,但不會保留請求參數的順序。此要求資料包括要求標頭、查詢字串參數、URL路徑變數、承載和API組態資料。組態資料可包含目前的部署階段名稱、階段變數、使用者身分或授權內容 (如果有)。後端 Lambda 函數會剖析傳入請求資料,以判斷其所傳回的回應。若要讓API閘道將 Lambda 輸出作為回API應傳遞給用戶端,Lambda 函數必須以此格式傳回結果。

由於API閘道不會在用戶端和後端 Lambda 函數之間進行很多介入 Lambda 代理整合,因此用戶端和整合的 Lambda 函數可以相互適應變更,而不會中斷. API 若要啟用這項功能,用戶端必須遵循後端 Lambda 函數所制定的應用程式通訊協定。

您可以為任何API方法設定 Lambda 代理整合。但是,當 Lambda 代理整合配置為涉及通用代理資源的API方法時,它會更有效。一般代理資源可由 {proxy+} 的特殊樣板化路徑變數、catch-all ANY 方法預留位置或兩者來表示。用戶端可以在傳入請求中將輸入當作請求參數或適用的承載傳遞到後端 Lambda 函數。要求參數包括標頭、URL路徑變數、查詢字串參數和適用的承載。整合的 Lambda 函數會驗證所有輸入來源,再處理請求,如果遺失所要求的任何輸入,則會以有意義的錯誤訊息來回應用戶端。

當呼叫與的泛型API方HTTP法ANY和泛型資源整合的方法時{proxy+},用戶端會以特定HTTP方法提交要求來取代ANY。用戶端也會指定特定URL路徑{proxy+},而不是指定任何必要的標頭、查詢字串參數或適用的裝載。

下列清單摘要說明不同API方法與 Lambda Proxy 整合的執行階段行為:

  • ANY /{proxy+}:用戶端必須選擇特定HTTP方法、必須設定特定的資源路徑階層,並且可以設定任何標頭、查詢字串參數和適用的裝載,以將資料當做輸入傳遞至整合的 Lambda 函數。

  • ANY /res:用戶端必須選擇特定HTTP方法,並且可以設定任何標頭、查詢字串參數和適用的裝載,以將資料做為輸入傳遞至整合的 Lambda 函數。

  • GET|POST|PUT|... /{proxy+}:用戶端可設定特定資源路徑階層、任何標頭、查詢字串參數與適用的承載,以將資料作為輸入傳遞至整合的 Lambda 函數。

  • GET|POST|PUT|... /res/{path}/...:用戶端必須選擇特定路徑區段 (針對 {path} 變數),並可設定任何請求標頭、查詢字串參數與適用的承載,以將輸入資料傳遞至整合的 Lambda 函數。

  • GET|POST|PUT|... /res:用戶端可選擇任何請求標頭、查詢字串參數與適用的承載,以將輸入資料傳遞至整合的 Lambda 函數。

{proxy+} 的代理資源與 {custom} 的自訂資源都可使用樣板化路徑變數來表示。不過,{proxy+} 可參考沿著路徑階層的任何資源,但 {custom} 只能參考特定路徑區段。例如,雜貨店可能會依部門名稱、產品類別與產品類型,來組織其線上產品庫存。雜貨店的網站可接著透過自訂資源的下列樣板化路徑變數來表示可用的產品:/{department}/{produce-category}/{product-type}。例如,蘋果是以 /produce/fruit/apple 表示,而紅蘿蔔是以 /produce/vegetables/carrot 表示。它也可以使用 /{proxy+} 來表示客戶在線上商店購物時可搜尋的任何部門、任何產品類別或任何產品類型。例如,/{proxy+} 可參考下列任何項目:

  • /produce

  • /produce/fruit

  • /produce/vegetables/carrot

若要讓客戶搜尋任何可用的產品、其產品類別與相關聯的商店部門,您可以公開 GET /{proxy+} 的單一方法並授予唯讀許可。同樣地,若要讓主管更新 produce 部門的庫存,您可以設定 PUT /produce/{proxy+} 的另一個單一方法並授予讀取/寫入許可。若要讓出納員更新蔬菜的計算加總,您可以設定 POST /produce/vegetables/{proxy+} 方法並授予讀取/寫入許可。若要讓商店經理對任何可用的產品執行任何可能的動作,線上商店開發人員可以公開 ANY /{proxy+} 方法並授予讀取/寫入許可。在任何情況下,客戶或員工都必須在執行階段選取所選部門中指定類型的特定產品、所選部門中的特定產品類別或特定部門。

如需設定API閘道代理整合的詳細資訊,請參閱設定代理整合與代理資源

代理整合需要用戶端更詳細了解後端需求。因此,若要確保最佳應用程式效能與使用者體驗,後端開發人員必須向用戶端開發人員清楚表達後端的需求,並提供未符合需求時的完善錯誤回饋機制。

支援多值標頭和查詢字串參數

APIGateway 支援具有相同名稱的多個標頭和查詢字串參數。多值標頭以及單值標頭和參數可在相同的請求和回應中結合使用。如需詳細資訊,請參閱 代理整合之 Lambda 函數的輸入格式代理整合之 Lambda 函數的輸出格式

代理整合之 Lambda 函數的輸入格式

在 Lambda 代理整合中,API閘道會將整個用戶端要求對應至後端 Lambda 函event數的輸入參數。下列範例顯示API閘道傳送至 Lambda 代理整合的事件結構。

{ "resource": "/my/path", "path": "/my/path", "httpMethod": "GET", "headers": { "header1": "value1", "header2": "value1,value2" }, "multiValueHeaders": { "header1": [ "value1" ], "header2": [ "value1", "value2" ] }, "queryStringParameters": { "parameter1": "value1,value2", "parameter2": "value" }, "multiValueQueryStringParameters": { "parameter1": [ "value1", "value2" ], "parameter2": [ "value" ] }, "requestContext": { "accountId": "123456789012", "apiId": "id", "authorizer": { "claims": null, "scopes": null }, "domainName": "id.execute-api.us-east-1.amazonaws.com", "domainPrefix": "id", "extendedRequestId": "request-id", "httpMethod": "GET", "identity": { "accessKey": null, "accountId": null, "caller": null, "cognitoAuthenticationProvider": null, "cognitoAuthenticationType": null, "cognitoIdentityId": null, "cognitoIdentityPoolId": null, "principalOrgId": null, "sourceIp": "IP", "user": null, "userAgent": "user-agent", "userArn": null, "clientCert": { "clientCertPem": "CERT_CONTENT", "subjectDN": "www.example.com", "issuerDN": "Example issuer", "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1", "validity": { "notBefore": "May 28 12:30:02 2019 GMT", "notAfter": "Aug 5 09:36:04 2021 GMT" } } }, "path": "/my/path", "protocol": "HTTP/1.1", "requestId": "id=", "requestTime": "04/Mar/2020:19:15:17 +0000", "requestTimeEpoch": 1583349317135, "resourceId": null, "resourcePath": "/my/path", "stage": "$default" }, "pathParameters": null, "stageVariables": null, "body": "Hello from Lambda!", "isBase64Encoded": false }
注意

在輸入中:

  • headers 鍵只能包含單一值標頭。

  • multiValueHeaders 鍵可以包含多值標頭以及單一值標頭。

  • 如果同時為headers和指定值multiValueHeaders,G API ateway 會將它們合併到單一清單中。如果在兩者指定了相同的鍵值對,則只有 multiValueHeaders 中的值會出現在合併清單。

在後端 Lambda 函數的輸入中,requestContext 物件是索引鍵/值組的映射。在各對中,鍵是 $context 變數屬性的名稱,而值是該屬性的值。API閘道可能會在地圖中新增金鑰。

根據已啟用的圖徵,requestContext地圖可能會有所不同API。API例如,在上述範例中,未指定任何授權類型,因此沒有 $context.authorizer.*$context.identity.* 屬性存在。指定授權類型時,這會導致 API Gateway 將授權使用者資訊傳遞至requestContext.identity物件中的整合端點,如下所示:

  • 當授權類型為 AWS_IAM 時,授權的使用者資訊包含 $context.identity.* 屬性。

  • 當授權類型為 COGNITO_USER_POOLS (Amazon Cognito 授權方) 時,授權的使用者資訊包含 $context.identity.cognito*$context.authorizer.claims.* 屬性。

  • 當授權類型為 CUSTOM (Lambda 授權方) 時,授權的使用者資訊包含 $context.authorizer.principalId 和其他適用的 $context.authorizer.* 屬性。

代理整合之 Lambda 函數的輸出格式

在 Lambda 代理整合中,API閘道要求後端 Lambda 函數根據下列JSON格式傳回輸出:

{ "isBase64Encoded": true|false, "statusCode": httpStatusCode, "headers": { "headerName": "headerValue", ... }, "multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... }, "body": "..." }

在輸出中:

  • 如果不再傳回額外的回應標頭,則可以不指定 headersmultiValueHeaders 鍵。

  • headers 鍵只能包含單一值標頭。

  • multiValueHeaders 鍵可以包含多值標頭以及單一值標頭。您可以使用 multiValueHeaders 鍵來指定所有額外標頭,包括任何單一值標頭。

  • 如果同時為headers和指定值multiValueHeaders,G API ateway 會將它們合併到單一清單中。如果在兩者指定了相同的鍵值對,則只有 multiValueHeaders 中的值會出現在合併清單。

若要啟CORS用 Lambda 代理整合,您必須新增Access-Control-Allow-Origin:domain-name至輸出headersdomain-name可以是*任何網域名稱。輸出 body 會封送處理至前端,以做為方法回應承載。如果 body 是二進位 Blob,您可以透過將 isBase64Encoded 設定為 true將其編碼為 Base64 編碼字串,並將 */* 設定為 Binary Media Type (二進位媒體類型)。否則,您可以將它設定為 false,或保留未指定。

注意

如需啟用二進位支援的詳細資訊,請參閱使用API閘道主控台啟用二進位支援。如需 Lambda 函數的範例,請參閱從API閘道中的 Lambda 代理整合傳回二進位媒體

如果函數輸出的格式不同,APIGateway 會傳回502 Bad Gateway錯誤回應。

若要在 Node.js 的 Lambda 函數中傳回回應,您可以使用以下命令:

  • 若要傳回成功結果,請呼叫 callback(null, {"statusCode": 200, "body": "results"})

  • 若要擲回例外狀況,請呼叫 callback(new Error('internal server error'))

  • 針對用戶端錯誤 (例如,如果遺失必要參數),您可以呼叫 callback(null, {"statusCode": 400, "body": "Missing parameters of ..."}) 傳回錯誤,而不擲回例外狀況。

在 Node.js 的 Lambda async 函數中,同等語法應為:

  • 若要傳回成功結果,請呼叫 return {"statusCode": 200, "body": "results"}

  • 若要擲回例外狀況,請呼叫 throw new Error("internal server error")

  • 針對用戶端錯誤 (例如,如果遺失必要參數),您可以呼叫 return {"statusCode": 400, "body": "Missing parameters of ..."} 傳回錯誤,而不擲回例外狀況。