

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

# 建立及管理 Lambda 函數 URL
<a name="urls-configuration"></a>

函數 URL 是 Lambda 函數專用的 HTTP(S) 端點。您可以透過 Lambda 主控台或 Lambda API 建立及設定函數 URL。

**提示**  
Lambda 提供兩種透過 HTTP 端點調用函數的方式：函數 URL 與 Amazon API Gateway。如果不確定哪種方法最適合自己的使用案例，請參閱[選取一種使用 HTTP 請求調用 Lambda 函數的方法](furls-http-invoke-decision.md)。

當您建立函數 URL 時，Lambda 會自動為您產生不重複的 URL 端點。函數 URL 一旦建立，其 URL 端點便永遠不會變更。函數 URL 端點的格式如下：

```
https://<url-id>.lambda-url.<region>.on.aws
```

**注意**  
下列 不支援函數 URLs AWS 區域：亞太區域 （海德拉巴） (`ap-south-2`)、亞太區域 （墨爾本） (`ap-southeast-4`)、亞太區域 （馬來西亞） (`ap-southeast-5`)、亞太區域 （紐西蘭） (`ap-southeast-6`)、亞太區域 （泰國） (`ap-southeast-7`)、亞太區域 （台北） (`ap-east-2`)、加拿大西部 （卡加利） (`ca-west-1`)、歐洲 （西班牙） (`eu-south-2`)、歐洲 （蘇黎世） (`eu-central-2`)、以色列 （特拉維夫） (`il-central-1`) 和中東 （阿拉伯聯合大公國） ()`me-central-1`)。

函數 URL 可支援雙堆疊，能同時支援 IPv4 和 IPv6。為函數設定函數 URL 後，您可以利用 Web 瀏覽器、curl、Postman 或任何 HTTP 用戶端，透過 HTTP(S) 端點呼叫函數。

**注意**  
您只能透過公有網際網路存取您的函數 URL。雖然 Lambda 函數確實支援 AWS PrivateLink，但函數 URL 不支援。

Lambda 函數 URL 使用[以資源為基礎的政策](access-control-resource-based.md)，妥善控管安全性和存取權。函數 URL 也支援跨來源資源共用 (CORS) 組態選項。

您可以將函數 URL 套用至任何函數別名或未發佈的`$LATEST`函數版本。函數 URL 無法新增至其他任何函數版本。

下一節說明如何使用 Lambda 主控台和 CloudFormation 範本建立 AWS CLI和管理函數 URL

**Topics**
+ [建立函數 URL (主控台)](#create-url-console)
+ [建立函數 URL (AWS CLI)](#create-url-cli)
+ [將函數 URL 新增至 CloudFormation 範本](#urls-cfn)
+ [跨來源資源共享 (CORS)](#urls-cors)
+ [調節函數 URL](#urls-throttling)
+ [停用函數 URL](#urls-deactivating)
+ [刪除函數 URL](#w2aac39c81c53)
+ [控制對 Lambda 函數 URL 的存取](urls-auth.md)
+ [呼叫 Lambda 函數 URL](urls-invocation.md)
+ [監控 Lambda 函數 URL](urls-monitoring.md)
+ [選取一種使用 HTTP 請求調用 Lambda 函數的方法](furls-http-invoke-decision.md)
+ [教學課程：使用 Lambda 函式 URL 建立 Webhook 端點](urls-webhook-tutorial.md)

## 建立函數 URL (主控台)
<a name="create-url-console"></a>

請遵循下列步驟，使用主控台建立函數 URL。

### 為現有函數建立函數 URL
<a name="create-url-existing-function"></a>

1. 開啟 Lambda 主控台中的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇您要為其建立函數 URL 的函數名稱。

1. 選擇 **Configuration** (組態) 標籤，然後選擇 **Function URL** (函數 URL)。

1. 選擇 **Create function URL** (建立函數 URL)。

1. 為 **Auth type** (驗證類型) 選擇 **AWS\$1IAM** 或 **NONE** (無)。如需函數 URL 身分驗證的詳細資訊，請參閱[存取控制](urls-auth.md)。

1. (選用) 選取 **Configure cross-origin resource sharing (CORS)** (設定跨來源資源共享 (CORS))，然後完成函數 URL 的 CORS 設定。如需 CORS 的詳細資訊，請參閱「[跨來源資源共享 (CORS)](#urls-cors)」。

1. 選擇**儲存**。

這樣即可為 `$LATEST` 未發佈版本的函數建立函數 URL。函數 URL 會顯示於主控台的 **Function overview** (函數概觀) 區段。

### 為現有別名建立函數 URL
<a name="create-url-existing-alias"></a>

1. 開啟 Lambda 主控台中的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 找到您要為其建立函數 URL 的函數別名，選擇其函數名稱。

1. 選擇 **Aliases** (別名) 標籤，接著找到您要為其建立函數 URL 的函數別名，選擇該別名的名稱。

1. 選擇 **Configuration** (組態) 標籤，然後選擇 **Function URL** (函數 URL)。

1. 選擇 **Create function URL** (建立函數 URL)。

1. 為 **Auth type** (驗證類型) 選擇 **AWS\$1IAM** 或 **NONE** (無)。如需函數 URL 身分驗證的詳細資訊，請參閱[存取控制](urls-auth.md)。

1. (選用) 選取 **Configure cross-origin resource sharing (CORS)** (設定跨來源資源共享 (CORS))，然後完成函數 URL 的 CORS 設定。如需 CORS 的詳細資訊，請參閱「[跨來源資源共享 (CORS)](#urls-cors)」。

1. 選擇**儲存**。

這樣即可為函數別名建立函數 URL。函數 URL 會顯示於主控台中別名的 **Function overview** (函數概觀) 區段。

### 使用函數 URL 建立新函數
<a name="create-url-new-function"></a>

**建立具有函數 URL 的新函數 (主控台)**

1. 開啟 Lambda 主控台中的 [函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇**建立函數**。

1. 在**基本資訊**下，請執行下列動作：

   1. 為 **Function name** (函數名稱) 輸入您函數的名稱，例如 **my-function**。

   1. 針對**執行時間**，選擇您偏好的語言執行時間，例如 **Node.js 24**。

   1. 為 **Architecture** (架構) 選擇 **x86\$164** 或 **arm64**。

   1. 展開 **Permissions** (許可)，接著選擇建立新的執行角色或使用現有角色。

1. 展開 **Advanced settings** (進階設定)，然後選取 **Function URL** (函數 URL)。

1. 為 **Auth type** (驗證類型) 選擇 **AWS\$1IAM** 或 **NONE** (無)。如需函數 URL 身分驗證的詳細資訊，請參閱[存取控制](urls-auth.md)。

1. (選用) 選取 **Configure cross-origin resource sharing (CORS)** (設定跨來源資源共享 (CORS))。只要您在建立函數的過程中選取此選項，在預設情形下，您的函數 URL 就能允許所有來源的請求。建立函數後，您可以編輯函數 URL 的 CORS 設定。如需 CORS 的詳細資訊，請參閱「[跨來源資源共享 (CORS)](#urls-cors)」。

1. 選擇**建立函數**。

這樣即可為 `$LATEST` 未發佈版本的函數建立具有函數 URL 的新函數。函數 URL 會顯示於主控台的 **Function overview** (函數概觀) 區段。

## 建立函數 URL (AWS CLI)
<a name="create-url-cli"></a>

若要使用 AWS Command Line Interface (AWS CLI) 為現有的 Lambda 函數建立函數 URL，請執行下列命令：

```
aws lambda create-function-url-config \
    --function-name my-function \
    --qualifier prod \ // optional
    --auth-type AWS_IAM
    --cors-config {AllowOrigins="https://example.com"} // optional
```

這會將函數 URL 新增至函數 **my-function** 的 **prod** 限定詞。如需這些組態參數的詳細資訊，請參閱 API 參考資料中的 [CreateFunctionUrlConfig](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunctionUrlConfig.html)。

**注意**  
若要透過 建立函數 URL AWS CLI，函數必須已存在。

## 將函數 URL 新增至 CloudFormation 範本
<a name="urls-cfn"></a>

若要將 `AWS::Lambda::Url` 資源新增至 CloudFormation 範本，請使用下列語法：

### JSON
<a name="urls-cfn-json"></a>

```
{
  "Type" : "AWS::Lambda::Url",
  "Properties" : {
      "AuthType" : String,
      "Cors" : Cors,
      "Qualifier" : String,
      "TargetFunctionArn" : String
    }
}
```

### YAML
<a name="urls-cfn-yaml"></a>

```
Type: AWS::Lambda::Url
Properties: 
  AuthType: String
  Cors: 
    Cors
  Qualifier: String
  TargetFunctionArn: String
```

### Parameters
<a name="urls-cfn-params"></a>
+ (必要) `AuthType` – 定義函數 URL 的身分驗證類型。可能的值為 `AWS_IAM` 或 `NONE`。如果您希望只讓完成身分驗證的使用者存取，請設為 `AWS_IAM`。如要繞過 IAM 身分驗證，並允許任何使用者向您的函數提出請求，請設為 `NONE`。
+ (選用) `Cors` – 定義函數 URL 的 [CORS 設定](#urls-cors)。如要將 `Cors` 新增至 CloudFormation 中的 `AWS::Lambda::Url` 資源，請使用下列語法。

    
**Example AWS::Lambda::Url.Cors (JSON)**  

  ```
  {
    "AllowCredentials" : Boolean,
    "AllowHeaders" : [ String, ... ],
    "AllowMethods" : [ String, ... ],
    "AllowOrigins" : [ String, ... ],
    "ExposeHeaders" : [ String, ... ],
    "MaxAge" : Integer
  }
  ```  
**Example AWS::Lambda::Url.Cors (YAML)**  

  ```
    AllowCredentials: Boolean
    AllowHeaders: 
      - String
    AllowMethods: 
      - String
    AllowOrigins: 
      - String
    ExposeHeaders: 
      - String
    MaxAge: Integer
  ```
+ (選用) `Qualifier` – 別名名稱。
+ (必要) `TargetFunctionArn` - Lambda 函數的名稱或 Amazon Resource Name (ARN)。有效名稱的格式包括：
  + **函數名稱** – `my-function`
  + **函數 ARN** – `arn:aws:lambda:us-west-2:123456789012:function:my-function`
  + **部分 ARN** – `123456789012:function:my-function`

## 跨來源資源共享 (CORS)
<a name="urls-cors"></a>

如要定義不同來源存取您函數 URL 的方式，請使用[跨來源資源共享 (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)。如果您打算從其他網域呼叫函數 URL，建議您設定 CORS。Lambda 為函數 URL 支援以下 CORS 標頭。


| CORS 標頭 | CORS 組態屬性 | 範例值 | 
| --- | --- | --- | 
|  [ Access-Control-Allow-Origin](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin)  |  `AllowOrigins`  |  `*` (允許所有來源) `https://www.example.com` `http://localhost:60905`  | 
|  [ Access-Control-Allow-Methods](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods)  |  `AllowMethods`  |  `GET`, `POST`, `DELETE`, `*`  | 
|  [ Access-Control-Allow-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers)  |  `AllowHeaders`  |  `Date`, `Keep-Alive`, `X-Custom-Header`  | 
|  [ Access-Control-Expose-Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers)  |  `ExposeHeaders`  |  `Date`, `Keep-Alive`, `X-Custom-Header`  | 
|  [ Access-Control-Allow-Credentials](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials)  |  `AllowCredentials`  |  `TRUE`  | 
|  [ Access-Control-Max-Age](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age)  |  `MaxAge`  |  `5` (預設)、`300`  | 

當您使用 Lambda 主控台或 設定函數 URL 的 CORS 時 AWS CLI，Lambda 會自動透過函數 URL 將 CORS 標頭新增至所有回應。或者，您也可以手動將 CORS 標頭新增至函數回應中。如果有衝突的標頭，預期的行為取決於請求的類型：
+ 對於 OPTIONS 請求等預檢請求，函數 URL 上設定的 CORS 標頭優先。Lambda 只會在回應中傳回這些 CORS 標頭。
+ 對於 GET 或 POST 請求等非預檢請求，Lambda 會傳回函數 URL 上設定的 CORS 標頭，以及函數傳回的 CORS 標頭。這可能會導致回應中出現重複的 CORS 標頭。您可能會看到類似如下的錯誤：`The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed`。

一般而言，我們建議在函數 URL 上設定所有 CORS 設定，而不是在函數回應中手動傳送 CORS 標頭。

## 調節函數 URL
<a name="urls-throttling"></a>

調節作業會限制函數處理請求的速度。這在許多情況下都相當實用，例如防止函數多載下游資源，或處理突然激增的請求數。

您可以設定預留並行，調節 Lambda 函數透過函數 URL 處理請求的速度。預留並行可限制函數的並行呼叫次數上限。函數的每秒請求率 (RPS) 上限相當於所設定預留並行數的 10 倍。例如，如果您將函數的預留並行值設為 100，則 RPS 最高為 1,000。

每當函數並行數量超過預留的並行數，函數 URL 就會傳回 HTTP `429` 狀態碼。如果函數收到的請求超過所設定預留並行數 10 倍的 RPS 最大值，您也會收到 HTTP `429` 錯誤。如需預留並行的詳細資訊，請參閱「[設定函數的預留並行](configuration-concurrency.md)」。

## 停用函數 URL
<a name="urls-deactivating"></a>

在緊急情況下，您可能會希望拒絕傳入函數 URL 的所有流量。若要停用函數 URL，請將預留並行設為零。這樣就能調節函數 URL 收到的所有請求，進而使 URL 傳回 HTTP `429` 狀態回應。如要重新啟動函數 URL，請刪除預留並行的組態，或將組態設為大於零的數量。

## 刪除函數 URL
<a name="w2aac39c81c53"></a>

當您刪除函數 URL，您就無法復原。建立新函數 URL 會產生不同的 URL 地址。

**注意**  
如果您刪除具有驗證類型 `NONE` 的函數 URL，Lambda 不會自動刪除關聯的資源型政策。如果您想要刪除此政策，則必須手動執行。

1. 開啟 Lambda 主控台中的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇函數的名稱。

1. 選擇 **Configuration** (組態) 標籤，然後選擇 **Function URL** (函數 URL)。

1. 選擇 **刪除**。

1. 將 *delete* 一詞輸入欄位以確認刪除。

1. 選擇 **刪除**。

**注意**  
當您刪除具有函數 URL 的函數時，Lambda 會非同步刪除相應的函數 URL。如果您立即在相同帳戶中建立具有相同名稱的新函數，則原來的函數 URL 可能會映射到新的函數，而不會被刪除。

# 控制對 Lambda 函數 URL 的存取
<a name="urls-auth"></a>

**注意**  
自 2025 年 10 月起，新的函數 URL 將同時需要 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction` 許可。

您可以透過 [AuthType](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunctionUrlConfig.html#lambda-CreateFunctionUrlConfig-request-AuthType) 參數及連接至特定函數的[資源型政策](access-control-resource-based.md)，控制 Lambda 函數 URL 的存取權。這兩個元件的組態能決定誰可以對函數 URL 呼叫或執行其他管理動作。

`AuthType` 參數決定 Lambda 如何對函數 URL 的請求執行身分驗證或授權。設定函數 URL 時，您必須指定以下任一 `AuthType` 選項：
+ `AWS_IAM` – Lambda 使用 AWS Identity and Access Management (IAM) 根據 IAM 主體的身分政策和函數的資源型政策來驗證和授權請求。如果您希望僅允許已進行身分驗證的使用者和角色透過函數 URL 來調用函數，請選擇此選項。
+ `NONE` – Lambda 不會在呼叫函數前執行任何身分驗證。然而，函數的資源型政策永遠有效，而且您必須授予公有存取權，您的函數 URL 才能接收請求。選擇此選項，即可允許使用者公開存取函數 URL，而且不必完成身分驗證。

如需安全性的其他洞見，您可以使用 AWS Identity and Access Management Access Analyzer 來取得對函數 URL 的外部存取的完整分析。IAM Access Analyzer 也能監控您 Lambda 函數新增或更新的許可，以協助您識別授予公有和跨帳戶存取權的許可。您可以免費使用 IAM Access Analyzer。若要開始使用 IAM Access Analyzer，請參閱[使用 AWS IAM Access Analyzer](https://docs.aws.amazon.com/IAM/latest/UserGuide/what-is-access-analyzer.html)。

本頁提供了針對兩種身分驗證類型的資源型政策範例，也說明了如何使用 [AddPermission](https://docs.aws.amazon.com/lambda/latest/api/API_AddPermission.html) API 操作或 Lambda 主控台來建立這些政策。如需有關設定許可後如何調用函數 URL 的資訊，請參閱[呼叫 Lambda 函數 URL](urls-invocation.md)。

**Topics**
+ [使用 `AWS_IAM` 驗證類型](#urls-auth-iam)
+ [使用 `NONE` 驗證類型](#urls-auth-none)
+ [控管和存取權控制](#urls-governance)

## 使用 `AWS_IAM` 驗證類型
<a name="urls-auth-iam"></a>

如果您選擇採用 `AWS_IAM` 身分驗證類型，則使用者必須擁有 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction` 許可才能調用 Lambda 函數 URL。視提出調用請求的使用者而定，您可能需要透過[資源型政策](access-control-resource-based.md)才能授予此許可。

如果提出請求的委託人與函數 URL AWS 帳戶 位於相同位置，則委託人必須在其[身分型政策](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_identity-vs-resource.html)中****具有 `lambda:InvokeFunctionUrl`和 `lambda:InvokeFunction` 許可，**或在**函數的資源型政策中授予許可。換言之，若使用者已經透過資源型政策取得 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction` 許可，即可自行決定是否使用身分型政策。政策評估需遵循 [Policy evaluation logic](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic.html) 中概述的規則。

如果提出請求的主體位於不同帳戶，則主體必須**同時**透過身分型政策取得 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction` 許可，**並且**針對其嘗試調用的函式，透過資源型政策取得許可。政策評估需遵循 [Determining whether a cross-account request is allowed](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic-cross-account.html#policy-eval-cross-account) 中概述的規則。

下列資源型政策允許 中`example` AWS 帳戶 `444455556666`的角色叫用與函數 相關聯的函數 URL`my-function`。[lambda：InvokedViaFunctionUrl](https://docs.aws.amazon.com/lambda/latest/api/API_AddPermission.html#lambda-AddPermission-request-InvokedViaFunctionUrl) 內容索引鍵會將 `lambda:InvokeFunction` 動作限制為函數 URL 呼叫。這意味著主體必須使用函數 URL 來調用函數。如未包含 `lambda:InvokedViaFunctionUrl`，則主體除了函數 URL 外，還可以透過其他調用方法來調用函數。

**Example – 跨帳戶資源型政策**    
****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::444455556666:role/example"
      },
      "Action": "lambda:InvokeFunctionUrl",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:my-function",
      "Condition": {
        "StringEquals": {
          "lambda:FunctionUrlAuthType": "AWS_IAM"
        }
      }
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::444455556666:role/example"
      },
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-1:123456789012:function:my-function",
      "Condition": {
        "Bool": {
          "lambda:InvokedViaFunctionUrl": "true"
        }
      }
    }
  ]
}
```

您可以依照下列步驟，透過主控台建立此資源型政策：

**將 URL 呼叫許可授予其他帳戶 (主控台)**

1. 開啟 Lambda 主控台中的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇您要授予 URL 呼叫許可的函數名稱。

1. 依序選擇 **Configuration** (組態) 索引標籤和 **Permissions** (許可)。

1. 在 **Resource-based policy** (資源型政策) 底下，選擇 **Add permissions** (新增許可)。

1. 選擇 **Function URL** (函數 URL)。

1. 針對 **Auth type** (驗證類型) 選擇 **AW\$1IAM**。

1. 輸入政策陳述式的**陳述式 ID**。

1. 依據要向其授予許可的使用者或角色，在**主體**中輸入其帳戶 ID 或 Amazon Resource Name (ARN)。例如：**444455556666**。

1. 選擇**儲存**。

或者，您可以使用下列 [add-permission](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/add-permission.html) AWS Command Line Interface (AWS CLI) 命令建立此政策。使用 時 AWS CLI，您必須分別新增 `lambda:InvokeFunctionUrl`和 `lambda:InvokeFunction`陳述式。例如：

```
aws lambda add-permission --function-name my-function \
  --statement-id UrlPolicyInvokeURL \
  --action lambda:InvokeFunctionUrl \
  --principal 444455556666 \
  --function-url-auth-type AWS_IAM
```

```
aws lambda add-permission --function-name my-function \
  --statement-id UrlPolicyInvokeFunction \
  --action lambda:InvokeFunction \
  --principal 444455556666 \
  --invoked-via-function-url
```

## 使用 `NONE` 驗證類型
<a name="urls-auth-none"></a>

**重要**  
當函數 URL 身分驗證類型為 `NONE`，並且透過[資源型政策](access-control-resource-based.md)授予公有存取權時，任何未經身分驗證的使用者只要取得函數 URL，即可調用對應函數。

在部分情況下，您可能需要將函數 URL 設定為公開存取。例如，您可能希望為直接透過 Web 瀏覽器提出的請求提供服務。如要允許使用者公開存取您的函數 URL，請選擇 `NONE` 驗證類型。

如果您選擇 `NONE` 驗證類型，Lambda 就不會使用 IAM 對存取函數 URL 的請求執行身分驗證。但是，函式必須具有允許 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction` 的資源型政策。當您`NONE`使用主控台或 AWS Serverless Application Model (AWS SAM) 建立具有身分驗證類型的函數 URL 時，Lambda 會自動為您建立以資源為基礎的政策。如果您直接使用 AWS CloudFormation AWS CLI或 Lambda API，則必須[自行新增政策](#policy-cli)。

建議在使用 `NONE` 身分驗證類型時，在資源型政策中包含 [lambda:InvokedViaFunctionUrl](https://docs.aws.amazon.com/lambda/latest/api/API_AddPermission.html#lambda-AddPermission-request-InvokedViaFunctionUrl) 內容索引鍵。此內容索引鍵可確保函數只能透過函數 URL 調用，而不能透過其他調用方法調用。

請注意有關此政策的下列資訊：
+ 所有實體都可以呼叫 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction`。這意味著任何擁有函數 URL 的使用者都可以調用函數。
+ `lambda:FunctionUrlAuthType` 條件索引鍵值為 `NONE`。這意味著，唯有當函數 URL 的身分驗證類型也是 `NONE` 時，此政策陳述式才會允許您存取函數 URL。
+ `lambda:InvokedViaFunctionUrl` 條件可確保函數只能透過函數 URL 調用，而不能透過其他調用方法調用。

**Example – NONE 身分驗證類型的預設資源型政策**    
****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [
    {
      "Sid": "FunctionURLAllowPublicAccess",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "lambda:InvokeFunctionUrl",
      "Resource": "arn:aws:lambda:us-east-2:123456789012:function:my-function",
      "Condition": {
        "StringEquals": {
          "lambda:FunctionUrlAuthType": "NONE"
        }
      }
    },
    {
      "Sid": "FunctionURLInvokeAllowPublicAccess",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:us-east-2:123456789012:function:my-function",
      "Condition": {
        "Bool": {
          "lambda:InvokedViaFunctionUrl": "true"
        }
      }
    }
  ]
}
```

**使用 建立資源型政策 AWS CLI**  
除非您使用 主控台或 AWS SAM 建立身分驗證類型為 的函數 URL`NONE`，否則您必須自行新增資源型政策。使用下列命令為 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction` 許可建立陳述式。每個陳述式都必須在個別命令中進行新增。

```
aws lambda add-permission \
  --function-name UrlTestFunction \
  --statement-id UrlPolicyInvokeURL \
  --action lambda:InvokeFunctionUrl \
  --principal * \
  --function-url-auth-type NONE
```

```
aws lambda add-permission \
  --function-name UrlTestFunction \
  --statement-id UrlPolicyInvokeFunction \
  --action lambda:InvokeFunction \
  --principal * \
  --invoked-via-function-url
```

**注意**  
如果您刪除具有驗證類型 `NONE` 的函數 URL，Lambda 不會自動刪除關聯的資源型政策。如果您想要刪除此政策，則必須手動執行。

如果函數資源型政策並未授予 `lambda:invokeFunctionUrl` 和 `lambda:InvokeFunction` 許可，則當使用者嘗試調用函數 URL 時，將收到 403 Forbidden 錯誤代碼。即使函數 URL 使用 `NONE` 身分驗證類型，也會發生這種情況。

## 控管和存取權控制
<a name="urls-governance"></a>

除了函數 URL 呼叫許可之外，您也可以控制函數 URL 設定動作的存取權。Lambda 支援以下適用於函數 URL 的 IAM 政策動作：
+ `lambda:InvokeFunctionUrl` – 使用函數 URL 呼叫 Lambda 函數。
+ `lambda:CreateFunctionUrlConfig` – 建立函數 URL 並設定其 `AuthType`。
+ `lambda:UpdateFunctionUrlConfig` – 更新函數 URL 組態及其 `AuthType`。
+ `lambda:GetFunctionUrlConfig` – 檢視函數 URL 的詳細資訊。
+ `lambda:ListFunctionUrlConfigs` – 列出函數 URL 組態。
+ `lambda:DeleteFunctionUrlConfig` – 刪除函數 URL。

若要允許或拒絕其他 AWS 實體的函數 URL 存取，請在 IAM 政策中包含這些動作。例如，下列政策授予 `example`角色 AWS 帳戶 更新**my-function**帳戶 中函數的函數 URL 的`444455556666`許可`123456789012`。

**Example 跨帳戶函數 URL 政策**    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": { 
                "AWS": "arn:aws:iam::444455556666:role/example"
            },
            "Action": "lambda:UpdateFunctionUrlConfig",
            "Resource": "arn:aws:lambda:us-east-2:123456789012:function:my-function"
        }
    ]
}
```

### 條件索引鍵
<a name="urls-condition-keys"></a>

如要精細控制函數 URL 的存取權，請使用條件內容索引鍵。Lambda 為函數 URL 支援下列內容索引鍵：
+ `lambda:FunctionUrlAuthType`：定義描述函數 URL 所用身分驗證類型的列舉值。此值可以是 `AWS_IAM` 或 `NONE`。
+ `lambda:InvokedViaFunctionUrl`：將 `lambda:InvokeFunction` 動作限制為透過函數 URL 進行的呼叫。這可確保該函數只能使用函數 URL 調用，而不能透過其他調用方法調用。如需使用 `lambda:InvokedViaFunctionUrl` 內容索引鍵的資源型政策範例，請參閱[使用 `AWS_IAM` 驗證類型](#urls-auth-iam)與[使用 `NONE` 驗證類型](#urls-auth-none)中的範例。

您可以在與函式相關聯的政策中使用這些內容索引鍵。例如，您可能希望限制哪些人可以變更函數 URL 的組態。若要針對 URL 驗證類型為 `NONE` 的所有函數拒絕所有 `UpdateFunctionUrlConfig` 請求，您可以定義以下政策：

**Example 明確拒絕請求的函數 URL 政策**    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action":[
                "lambda:UpdateFunctionUrlConfig"
            ],
            "Resource": "arn:aws:lambda:us-east-1:123456789012:function:*",
            "Condition": {
                "StringEquals": {
                    "lambda:FunctionUrlAuthType": "NONE"
                }
            }
        }
    ]
}
```

若要授予 `example`角色 AWS 帳戶 `444455556666`許可，以對 URL 驗證類型為 的函數進行 `CreateFunctionUrlConfig`和 `UpdateFunctionUrlConfig`請求`AWS_IAM`，您可以定義下列政策：

**Example 明確允許請求的函數 URL 政策**    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": { 
                "AWS": "arn:aws:iam::444455556666:role/example"
            },
            "Action":[
                "lambda:CreateFunctionUrlConfig",
                "lambda:UpdateFunctionUrlConfig"
            ],
            "Resource": "arn:aws:lambda:us-east-1:123456789012:function:*",
            "Condition": {
                "StringEquals": {
                    "lambda:FunctionUrlAuthType": "AWS_IAM"
                }
            }
        }
    ]
}
```

您也可以在服[務控制政策](https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps.html)(SCP) 中使用此條件索引鍵。在 AWS Organizations中使用 SCP 管理整個組織的許可。例如，若要拒絕使用者建立或更新使用 `AWS_IAM` 以外驗證類型的函數 URL，請使用以下服務控制政策：

**Example 明確拒絕請求的函數 URL SCP**    
****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Deny",
            "Action":[
                "lambda:CreateFunctionUrlConfig",
                "lambda:UpdateFunctionUrlConfig"
            ],
            "Resource": "arn:aws:lambda:*:123456789012:function:*",
            "Condition": {
                "StringNotEquals": {
                    "lambda:FunctionUrlAuthType": "AWS_IAM"
                }
            }
        }
    ]
}
```

# 呼叫 Lambda 函數 URL
<a name="urls-invocation"></a>

函數 URL 是 Lambda 函數專用的 HTTP(S) 端點。您可以透過 Lambda 主控台或 Lambda API 建立及設定函數 URL。

**提示**  
Lambda 提供兩種透過 HTTP 端點調用函式的方式：函式 URL 與 Amazon API Gateway。如果不確定哪種方法最適合自己的使用案例，請參閱[選取一種使用 HTTP 請求調用 Lambda 函數的方法](furls-http-invoke-decision.md)。

當您建立函數 URL 時，Lambda 會自動為您產生不重複的 URL 端點。函數 URL 一旦建立，其 URL 端點便永遠不會變更。函數 URL 端點的格式如下：

```
https://<url-id>.lambda-url.<region>.on.aws
```

**注意**  
下列 AWS 區域不支援函式 URL：亞太區域 (海德拉巴) (`ap-south-2`)、亞太區域 (墨爾本) (`ap-southeast-4`)、亞太區域 (馬來西亞) (`ap-southeast-5`)、亞太區域 (紐西蘭) (`ap-southeast-6`)、亞太區域 (泰國) (`ap-southeast-7`)、亞太區域 (台北) (`ap-east-2`)、加拿大西部 (卡加利)(`ca-west-1`)、歐洲 (西班牙) (`eu-south-2`)、歐洲 (蘇黎世) (`eu-central-2`)、以色列 (特拉維夫) (`il-central-1`) 以及中東 (阿拉伯聯合大公國) (`me-central-1`)。

函數 URL 可支援雙堆疊，能同時支援 IPv4 和 IPv6。設定函數 URL 後，您可以利用 Web 瀏覽器、curl、Postman 或任何 HTTP 用戶端，透過 HTTP(S) 端點呼叫函數。若要調用函式 URL，您必須擁有 `lambda:InvokeFunctionUrl` 和 `lambda:InvokeFunction` 許可。如需更多詳細資訊，請參閱 [存取控制](urls-auth.md)。

**Topics**
+ [函數 URL 呼叫基礎知識](#urls-invocation-basics)
+ [請求和回應承載](#urls-payloads)

## 函數 URL 呼叫基礎知識
<a name="urls-invocation-basics"></a>

如果您的函數 URL 使用 `AWS_IAM` 驗證類型，您必須使用 [AWS Signature 第 4 版 (SigV4)](https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html) 簽署各個 HTTP 請求。[Postman](https://quickstarts.postman.com/guide/aws/index.html?index=..%2F..index#2) 等工具提供使用 SigV4 簽署請求的內建功能。

如果您不使用工具簽署函數 URL 的 HTTP 請求，則必須使用 SigV4 手動簽署各個請求。您的函數 URL 收到請求時，Lambda 也會計算 SigV4 簽章。唯有簽章相符，Lambda 才會處理請求。如需使用 SigV4 手動簽署請求的相關說明，請參閱《Amazon Web Services 一般參考 指南》**中的[使用 Signature 第 4 版簽署 AWS 請求](https://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html)。

如果您的函數 URL 使用 `NONE` 驗證類型，您不必使用 SigV4 簽署請求。您可以使用 Web 瀏覽器、curl、Postman 或任何 HTTP 用戶端來呼叫您的函數。

如要測試函數的簡易 `GET` 請求，請使用 Web 瀏覽器。例如，如果函數 URL 為 `https://abcdefg.lambda-url.us-east-1.on.aws`，而且接受字串參數 `message`，則請求 URL 可能如下所示：

```
https://abcdefg.lambda-url.us-east-1.on.aws/?message=HelloWorld
```

如要測試其他 HTTP 請求 (例如 `POST` 請求)，您可以使用 curl 等工具。例如，如果您希望在函數 URL 的 `POST` 請求中納入某些 JSON 資料，您可以使用下列 curl 命令：

```
curl -v 'https://abcdefg.lambda-url.us-east-1.on.aws/?message=HelloWorld' \
-H 'content-type: application/json' \
-d '{ "example": "test" }'
```

## 請求和回應承載
<a name="urls-payloads"></a>

用戶端呼叫您的函數 URL 時，Lambda 會先將請求映射至事件物件，再將請求傳遞給函數。接著，函數的回應會映射至 Lambda 透過函數 URL 回傳給用戶端的 HTTP 回應。

請求和回應事件格式會採取與 [Amazon API Gateway 承載格式 2.0 版](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.proxy-format)一樣的結構描述。

### 請求承載格式
<a name="urls-request-payload"></a>

請求承載的結構如下：

```
{
  "version": "2.0",
  "routeKey": "$default",
  "rawPath": "/my/path",
  "rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
  "cookies": [
    "cookie1",
    "cookie2"
  ],
  "headers": {
    "header1": "value1",
    "header2": "value1,value2"
  },
  "queryStringParameters": {
    "parameter1": "value1,value2",
    "parameter2": "value"
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "<urlid>",
    "authentication": null,
    "authorizer": {
        "iam": {
                "accessKey": "AKIA...",
                "accountId": "111122223333",
                "callerId": "AIDA...",
                "cognitoIdentity": null,
                "principalOrgId": null,
                "userArn": "arn:aws:iam::111122223333:user/example-user",
                "userId": "AIDA..."
        }
    },
    "domainName": "<url-id>.lambda-url.us-west-2.on.aws",
    "domainPrefix": "<url-id>",
    "http": {
      "method": "POST",
      "path": "/my/path",
      "protocol": "HTTP/1.1",
      "sourceIp": "123.123.123.123",
      "userAgent": "agent"
    },
    "requestId": "id",
    "routeKey": "$default",
    "stage": "$default",
    "time": "12/Mar/2020:19:03:58 +0000",
    "timeEpoch": 1583348638390
  },
  "body": "Hello from client!",
  "pathParameters": null,
  "isBase64Encoded": false,
  "stageVariables": null
}
```


| 參數 | 描述 | 範例 | 
| --- | --- | --- | 
|  `version`  |  此事件的承載格式版本。Lambda 函數 URL 目前支援[承載格式 2.0 版](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html#http-api-develop-integrations-lambda.proxy-format)。  |  `2.0`  | 
|  `routeKey`  |  函數 URL 不使用此參數。Lambda 將此設為 `$default` 作為預留位置使用。  |  `$default`  | 
|  `rawPath`  |  請求路徑。例如，如果請求 URL 為 `https://{url-id}.lambda-url.{region}.on.aws/example/test/demo`，則原始路徑值為 `/example/test/demo`。  |  `/example/test/demo`  | 
|  `rawQueryString`  |  內含請求查詢字串參數的原始字串。支援的字元包含 `a-z`、`A-Z`、`0-9`、`.`、`_`、`-`、`%`、`&`、`=`，以及 `+`。  |  `"?parameter1=value1&parameter2=value2"`  | 
|  `cookies`  |  內含隨請求一併傳送之所有 Cookie 的陣列。  |  `["Cookie_1=Value_1", "Cookie_2=Value_2"]`  | 
|  `headers`  |  以鍵值對形式呈現的請求標頭清單。  |  `{"header1": "value1", "header2": "value2"}`  | 
|  `queryStringParameters`  |  請求的查詢參數。例如，如果請求 URL 為 `https://{url-id}.lambda-url.{region}.on.aws/example?name=Jane`，則 `queryStringParameters` 值為具備索引鍵 `name` 和值 `Jane` 的 JSON 物件。  |  `{"name": "Jane"}`  | 
|  `requestContext`  |  內含請求其他資訊的物件，例如 `requestId`、請求的時間，以及呼叫者的身分 (如果透過 AWS Identity and Access Management (IAM) 取得授權的話)。  |   | 
|  `requestContext.accountId`  |  函數擁有者的 AWS 帳戶 ID。  |  `"123456789012"`  | 
|  `requestContext.apiId`  |  函數 URL 的 ID。  |  `"33anwqw8fj"`  | 
|  `requestContext.authentication`  |  函數 URL 不使用此參數。Lambda 將此設為 `null`。  |  `null`  | 
|  `requestContext.authorizer`  |  內含呼叫者身分相關資訊的物件 (如果函數 URL 使用 `AWS_IAM` 驗證類型的話)，否則 Lambda 會將此設為 `null`。  |   | 
|  `requestContext.authorizer.iam.accessKey`  |  呼叫者身分的存取金鑰。  |  `"AKIAIOSFODNN7EXAMPLE"`  | 
|  `requestContext.authorizer.iam.accountId`  |  呼叫者身分的 AWS 帳戶 ID。  |  `"111122223333"`  | 
|  `requestContext.authorizer.iam.callerId`  |  呼叫者的 ID (使用者 ID)。  |  `"AIDACKCEVSQ6C2EXAMPLE"`  | 
|  `requestContext.authorizer.iam.cognitoIdentity`  |  函數 URL 不使用此參數。Lambda 將此設為 `null`，或將此從 JSON 排除。  |  `null`  | 
|  `requestContext.authorizer.iam.principalOrgId`  |  與呼叫者身分相關聯的委託人組織 ID。  |  `"AIDACKCEVSQORGEXAMPLE"`  | 
|  `requestContext.authorizer.iam.userArn`  |  呼叫者身分的使用者 Amazon Resource Name (ARN)。  |  `"arn:aws:iam::111122223333:user/example-user"`  | 
|  `requestContext.authorizer.iam.userId`  |  呼叫者身分的使用者 ID。  |  `"AIDACOSFODNN7EXAMPLE2"`  | 
|  `requestContext.domainName`  |  函數 URL 的網域名稱。  |  `"<url-id>.lambda-url.us-west-2.on.aws"`  | 
|  `requestContext.domainPrefix`  |  函數 URL 的網域前綴。  |  `"<url-id>"`  | 
|  `requestContext.http`  |  內含 HTTP 請求詳細資訊的物件。  |   | 
|  `requestContext.http.method`  |  此請求所採用的 HTTP 方法。有效值包括 `GET`、`POST`、`PUT`、`HEAD`、`OPTIONS`、`PATCH` 和 `DELETE`。  |  `GET`  | 
|  `requestContext.http.path`  |  請求路徑。例如，如果請求 URL 為 `https://{url-id}.lambda-url.{region}.on.aws/example/test/demo`，則路徑值為 `/example/test/demo`。  |  `/example/test/demo`  | 
|  `requestContext.http.protocol`  |  請求的通訊協定。  |  `HTTP/1.1`  | 
|  `requestContext.http.sourceIp`  |  提出請求之即時 TCP 連線的來源 IP 地址。  |  `123.123.123.123`  | 
|  `requestContext.http.userAgent`  |  使用者代理程式請求標頭的值。  |  `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) Gecko/20100101 Firefox/42.0`  | 
|  `requestContext.requestId`  |  呼叫請求的 ID。您可以使用此 ID 追蹤與函數相關的呼叫日誌。  |  `e1506fd5-9e7b-434f-bd42-4f8fa224b599`  | 
|  `requestContext.routeKey`  |  函數 URL 不使用此參數。Lambda 將此設為 `$default` 作為預留位置使用。  |  `$default`  | 
|  `requestContext.stage`  |  函數 URL 不使用此參數。Lambda 將此設為 `$default` 作為預留位置使用。  |  `$default`  | 
|  `requestContext.time`  |  請求的時間戳記。  |  `"07/Sep/2021:22:50:22 +0000"`  | 
|  `requestContext.timeEpoch`  |  Unix epoch 時間格式的請求時間戳記。  |  `"1631055022677"`  | 
|  `body`  |  請求的本文。如果請求的內容屬於二進位類型，則本文會採用 base64 編碼。  |  `{"key1": "value1", "key2": "value2"}`  | 
|  `pathParameters`  |  函數 URL 不使用此參數。Lambda 將此設為 `null`，或將此從 JSON 排除。  |  `null`  | 
|  `isBase64Encoded`  |  如果本文為二進位承載並採用 base64 編碼，此值為 `TRUE`，否則為 `FALSE`。  |  `FALSE`  | 
|  `stageVariables`  |  函數 URL 不使用此參數。Lambda 將此設為 `null`，或將此從 JSON 排除。  |  `null`  | 

### 回應承載格式
<a name="urls-response-payload"></a>

函數傳回回應時，Lambda 會剖析回應內容，並將其轉換為 HTTP 回應。函數回應承載的格式如下：

```
{
   "statusCode": 201,
    "headers": {
        "Content-Type": "application/json",
        "My-Custom-Header": "Custom Value"
    },
    "body": "{ \"message\": \"Hello, world!\" }",
    "cookies": [
        "Cookie_1=Value1; Expires=21 Oct 2021 07:48 GMT",
        "Cookie_2=Value2; Max-Age=78000"
    ],
    "isBase64Encoded": false
}
```

Lambda 會為您推斷回應格式。如果您的函數傳回有效的 JSON，但未傳回 `statusCode`，則 Lambda 會採取下列假設：
+ `statusCode`is(`200` )
**注意**  
有效 `statusCode` 的範圍為 100 至 599。
+ `content-type`is(`application/json` )
+ `body` 是函數的回應。
+ `isBase64Encoded`is(`false` )

以下範例顯示 Lambda 函數輸出與回應承載之間的映射情形，以及回應承載與最終 HTTP 回應之間的映射情形。用戶端呼叫您的函數 URL 時，會看見 HTTP 回應。

**字串回應的輸出範例**


| Lambda 函數輸出 | 轉譯後的回應輸出 | HTTP 回應 (用戶端看見的內容) | 
| --- | --- | --- | 
|  <pre>"Hello, world!"</pre>  |  <pre>{<br />  "statusCode": 200,<br />  "body": "Hello, world!",<br />  "headers": {<br />    "content-type": "application/json"<br />  },<br />  "isBase64Encoded": false<br />}</pre>  |  <pre>HTTP/2 200<br />date: Wed, 08 Sep 2021 18:02:24 GMT<br />content-type: application/json<br />content-length: 15<br /><br />"Hello, world!"</pre>  | 

**JSON 回應的輸出範例**


| Lambda 函數輸出 | 轉譯後的回應輸出 | HTTP 回應 (用戶端看見的內容) | 
| --- | --- | --- | 
|  <pre>{<br />  "message": "Hello, world!"<br />}</pre>  |  <pre>{<br />  "statusCode": 200,<br />  "body": {<br />    "message": "Hello, world!"<br />  },<br />  "headers": {<br />    "content-type": "application/json"<br />  },<br />  "isBase64Encoded": false<br />}</pre>  |  <pre>HTTP/2 200<br />date: Wed, 08 Sep 2021 18:02:24 GMT<br />content-type: application/json<br />content-length: 34<br /><br />{<br />  "message": "Hello, world!"<br />}</pre>  | 

**自訂回應的輸出範例**


| Lambda 函數輸出 | 轉譯後的回應輸出 | HTTP 回應 (用戶端看見的內容) | 
| --- | --- | --- | 
|  <pre>{<br />   "statusCode": 201,<br />    "headers": {<br />        "Content-Type": "application/json",<br />        "My-Custom-Header": "Custom Value"<br />    },<br />    "body": JSON.stringify({<br />        "message": "Hello, world!"<br />    }),<br />    "isBase64Encoded": false<br />}</pre>  |  <pre>{<br />   "statusCode": 201,<br />    "headers": {<br />        "Content-Type": "application/json",<br />        "My-Custom-Header": "Custom Value"<br />    },<br />    "body": JSON.stringify({<br />        "message": "Hello, world!"<br />    }),<br />    "isBase64Encoded": false<br />}</pre>  |  <pre>HTTP/2 201<br />date: Wed, 08 Sep 2021 18:02:24 GMT<br />content-type: application/json<br />content-length: 27<br />my-custom-header: Custom Value<br /><br />{<br />  "message": "Hello, world!"<br />}</pre>  | 

### Cookie
<a name="urls-cookies"></a>

如要從函數傳回 Cookie，請勿手動新增 `set-cookie` 標頭。您應將 Cookie 加入回應承載物件中。Lambda 會自動轉譯 Cookie，並以 `set-cookie` 標頭形式新增至 HTTP 回應，如下所示。


| Lambda 函數輸出 | HTTP 回應 (用戶端看見的內容) | 
| --- | --- | 
|  <pre>{<br />   "statusCode": 201,<br />    "headers": {<br />        "Content-Type": "application/json",<br />        "My-Custom-Header": "Custom Value"<br />    },<br />    "body": JSON.stringify({<br />        "message": "Hello, world!"<br />    }),<br />    "cookies": [<br />        "Cookie_1=Value1; Expires=21 Oct 2021 07:48 GMT",<br />        "Cookie_2=Value2; Max-Age=78000"<br />    ],<br />    "isBase64Encoded": false<br />}</pre>  |  <pre>HTTP/2 201<br />date: Wed, 08 Sep 2021 18:02:24 GMT<br />content-type: application/json<br />content-length: 27<br />my-custom-header: Custom Value<br />set-cookie: Cookie_1=Value2; Expires=21 Oct 2021 07:48 GMT<br />set-cookie: Cookie_2=Value2; Max-Age=78000<br /><br />{<br />  "message": "Hello, world!"<br />}</pre>  | 

# 監控 Lambda 函數 URL
<a name="urls-monitoring"></a>

您可以使用 AWS CloudTrail 和 Amazon CloudWatch 監控函數 URL。

**Topics**
+ [使用 CloudTrail 監控函數 URL](#urls-cloudtrail)
+ [函數 URL 的 CloudWatch 指標](#urls-cloudwatch)

## 使用 CloudTrail 監控函數 URL
<a name="urls-cloudtrail"></a>

針對函數 URL，Lambda 能將下列 API 操作記錄為 CloudTrail 日誌檔案事件：
+ [CreateFunctionUrlConfig](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunctionUrlConfig.html)
+ [UpdateFunctionUrlConfig](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionUrlConfig.html)
+ [DeleteFunctionUrlConfig](https://docs.aws.amazon.com/lambda/latest/api/API_DeleteFunctionUrlConfig.html)
+ [GetFunctionUrlConfig](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionUrlConfig.html)
+ [ListFunctionUrlConfigs](https://docs.aws.amazon.com/lambda/latest/api/API_ListFunctionUrlConfigs.html)

每個日誌項目都包含呼叫者身分、提出請求的時間，以及其他詳細資訊等相關資訊。您可以檢視 CloudTrail **事件歷史記錄**，查看過去 90 天內的所有事件。如要保留 90 天前的記錄，您可以建立線索。

預設情況下，CloudTrail 不會記錄 `InvokeFunctionUrl` 請求，系統會將這些請求視為資料事件。不過，您可以在 CloudTrail 中開啟資料事件記錄功能。如需詳細資訊，請參閱《AWS CloudTrail使用者指南》**中的[記錄資料事件](https://docs.aws.amazon.com/awscloudtrail/latest/userguide/logging-data-events-with-cloudtrail.html)。

## 函數 URL 的 CloudWatch 指標
<a name="urls-cloudwatch"></a>

Lambda 會將函數 URL 請求的彙總指標傳送到 CloudWatch。透過這些指標，您可以在 CloudWatch 主控台中監控函數 URL、建置儀錶板及設定警示。

函數 URL 支援以下呼叫指標。建議您搭配 `Sum` 統計數字一併檢視這些指標。
+ `UrlRequestCount` – 對此函數提出的請求數量。
+ `Url4xxCount` – 傳回 4XX HTTP 狀態碼的請求數量。收到 4XX 系列代碼表示用戶端發生錯誤，例如請求錯誤。
+ `Url5xxCount` – 傳回 5XX HTTP 狀態碼的請求數量。收到 5XX 系列代碼表示伺服器端發生錯誤，例如函數錯誤和逾時。

函數 URL 也支援以下效能指標。建議您搭配 `Average` 或 `Max` 統計數字一併檢視這些指標。
+ `UrlRequestLatency` – 函數 URL 從收到請求到傳回回應所經過的時間。

這些呼叫和效能指標均支援以下維度：
+ `FunctionName` – 針對指派給函數`$LATEST`未發佈版本或任何函數別名的函數 URL，查看其彙總指標，例如 `hello-world-function`。
+ `Resource` – 檢視特定函數 URL 的指標。您可使用函數名稱，並搭配函數未發佈的`$LATEST`版本或任一函數別名來加以定義，例如 `hello-world-function:$LATEST`。
+ `ExecutedVersion` – 根據所執行的版本檢視特定函數 URL 的指標。此維度的主要功能是追蹤指派給`$LATEST`未發佈版本的函數 URL。

# 選取一種使用 HTTP 請求調用 Lambda 函數的方法
<a name="furls-http-invoke-decision"></a>

Lambda 的許多常見使用案例涉及使用 HTTP 請求調用您的函數。例如，您可能希望 Web 應用程式透過瀏覽器請求調用您的函式。Lambda 函式也可用於建立完整的 REST API、處理來自行動應用程式的使用者互動、透過 HTTP 呼叫處理來自外部服務的資料，或建立自訂 Webhook。

以下各節說明透過 HTTP 調用 Lambda 的選擇，並提供資訊以協助您針對特定使用案例做出正確決策。

## 選取 HTTP 調用方法時，您有哪些選擇？
<a name="w2aac39c81c73b9"></a>

Lambda 提供兩種主要方法來使用 HTTP 請求調用函數 - [函數 URL](urls-configuration.md) 和 [API Gateway](services-apigateway.md)。這兩種選項的主要差異如下所示：
+ **Lambda 函數 URL** 可為 Lambda 函數提供簡單、直接的 HTTP 端點。已針對簡單性和成本效益對其進行最佳化，並提供透過 HTTP 公開 Lambda 函數的最快路徑。
+ **API Gateway** 是一種更進階的服務，用於建置功能完整的 API。API Gateway 已針對大規模建置和管理生產 API 進行最佳化，並提供完整的安全、監控和流量管理工具。

## 您已知道自己需求時的建議
<a name="w2aac39c81c73c11"></a>

如果您已經清楚自己的需求，以下是基本建議：

建議**[函數 URL](urls-configuration.md)** 用於簡單的應用程式或原型設計，其中您只需要基本的身分驗證方法和請求/回應處理，並想要將成本和複雜性降至最低。

**[API Gateway](services-apigateway.md)** 是大規模生產應用程式或需要更進階功能的情況的更佳選擇，例如 [OpenAPI Description](https://www.openapis.org/) 支援、身分驗證選項、自訂網域名稱或豐富的請求/回應處理，包括限流、快取和請求/回應轉換。

## 選擇調用 Lambda 函數的方法時應考慮的事項
<a name="w2aac39c81c73c13"></a>

在函數 URL 和 API Gateway 之間選取時，需要考慮下列因素：
+ 您的身分驗證需要，例如是否需要 OAuth 或 Amazon Cognito 來驗證使用者
+ 您的擴展需求以及您要實作之 API 的複雜性
+ 您是否需要進階功能，例如請求驗證和請求/回應格式化
+ 您的監控需求
+ 您的成本目標

透過了解這些因素，可以選擇最能平衡您的安全性、複雜性和成本需求的選項。

下列資訊摘要說明兩個選項之間的主要差異。

### 身分驗證
<a name="w2aac39c81c73c13c11b1"></a>
+ **函數 URLs**提供基本身分驗證選項。 AWS Identity and Access Management 可以將端點設定為公有 (無身分驗證) 或需要 IAM 身分驗證。透過 IAM 身分驗證，您可以使用標準 AWS 登入資料或 IAM 角色來控制存取。雖然設定簡單，但相較於其他驗證方法，此方法提供的選項有限。
+ **API Gateway** 可存取更全面的身分驗證選項。除了 IAM 身分驗證之外，也可以使用 [Lambda 授權工具](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html) (自訂身分驗證邏輯)、[Amazon Cognito](https://docs.aws.amazon.com/cognito/latest/developerguide/what-is-amazon-cognito.html) 使用者集區和 OAuth2.0 流程。此彈性可讓您實作複雜的身分驗證機制，包括第三方身分驗證提供者、權杖型身分驗證和多重要素身分驗證。

### 請求/回應處理
<a name="w2aac39c81c73c13c11b3"></a>
+ **函數 URL** 提供基本的 HTTP 請求和回應處理。它們支援標準 HTTP 方法，並包含內建的跨來源資源共用 (CORS) 支援。雖然他們可以自然處理 JSON 承載和查詢參數，但它們不提供請求轉換或驗證功能。回應處理同樣簡單 – 用戶端接收來自 Lambda 函數的回應，就像 Lambda 傳回它一樣。
+ **API Gateway** 可提供複雜的請求和回應處理功能。您可以定義請求驗證器，使用映射範本轉換請求和回應，設定請求/回應標頭，以及實作回應快取。API Gateway 也支援二進位承載和自訂網域名稱，並且可以在回應到達用戶端之前對其進行修改。可以使用 JSON 結構描述來設定請求/回應驗證和轉換的模型。

### 擴展
<a name="w2aac39c81c73c13c11b5"></a>
+ **函數 URL** 會根據 Lambda 函數的並行限制直接擴展，並透過將函數擴展到其設定的並行限制上限來處理流量尖峰。達到該限制後，Lambda 會使用 HTTP 429 回應來回應其他請求。沒有內建佇列機制，因此處理擴展完全取決於 Lambda 函數的組態。根據預設，Lambda 函數每個 有 1，000 個並行執行的限制 AWS 區域。
+ 除了 Lambda 自己的擴展之外，**API Gateway** 還提供其他擴展功能。它包含內建的請求佇列和限流控制，可讓您更輕鬆地管理流量尖峰。根據預設，API Gateway 每秒最多可以處理 10,000 個請求，高載容量為每秒 5,000 個請求。它也提供在不同層級調節請求的工具 (API、階段或方法)，以保護後端。

### 監控
<a name="w2aac39c81c73c13c11b7"></a>
+ **函數 URL** 透過 Amazon CloudWatch 指標提供基本監控，包括請求計數、延遲和錯誤率。可以存取標準 Lambda 指標和日誌，它們會顯示傳入函數的原始請求。雖然這可提供基本的操作可見性，但指標主要著重於函數執行。
+ **API Gateway** 提供全面的監控功能，包括詳細的指標、記錄和追蹤選項。可以透過 CloudWatch 來監控 API 呼叫、延遲、錯誤率和快取命中率/遺失率。API Gateway 也會整合 與 AWS X-Ray 以進行分散式追蹤，並提供可自訂的記錄格式。

### Cost
<a name="w2aac39c81c73c13c11b9"></a>
+ **函數 URL** 遵循標準 Lambda 定價模型 – 您只需支付函數調用和運算時間的費用。URL 端點本身不收取額外費用。如果您不需要 API Gateway 的其他功能，這對於簡單的 API 或低流量應用程式而言是一個具成本效益的選擇。
+ **API Gateway** 提供[免費方案](https://aws.amazon.com/api-gateway/pricing/#Free_Tier)，其中包含針對 REST API 收到的一百萬個 API 呼叫，以及針對 HTTP API 收到的一百萬個 API 呼叫。之後，API Gateway 會針對 API 呼叫、資料傳輸和快取 (如果啟用) 收取費用。請參閱 API Gateway [定價頁面](https://aws.amazon.com/api-gateway/pricing/)，了解您自己的使用案例費用。

### 其他功能
<a name="w2aac39c81c73c13c11c11"></a>
+ **函數 URL** 旨在實現簡便性和直接 Lambda 整合。它們支援 HTTP 和 HTTPS 端點，提供內建 CORS 支援，並提供雙堆疊 (IPv4 和 IPv6) 端點。雖然它們缺乏進階功能，但它們在您需要快速、直接地透過 HTTP 公開 Lambda 函數時表現卓越。
+ **API Gateway** 包含許多其他功能，例如 API 版本控制、階段管理、用於用量計劃的 API 金鑰、透過 Swagger/OpenAPI 的 API 文件、WebSocket API、VPC 中的私有 API 以及 WAF 整合，以提供額外的安全性。它還支援 Canary 部署、用於測試的模擬整合，以及與 Lambda AWS 服務 以外的其他 整合。

## 選取調用 Lambda 函數的方法
<a name="w2aac39c81c73c15"></a>

現在您已了解在 Lambda 函數 URL 和 API Gateway 之間進行選擇的條件，以及它們之間的主要差異，您可以選擇最符合您需求的選項，並使用下列資源來協助您開始使用。

------
#### [ Function URLs ]

**使用下列資源開始使用函數 URL**
+ 遵循教學課程[建立具有函數 URL 的 Lambda 函數](urls-webhook-tutorial.md)
+ 在本指南的 [建立及管理 Lambda 函數 URL](urls-configuration.md) 章節中進一步了解 函數 URL
+ 透過執行以下操作，嘗試主控台內的引導式教學課程**建立簡單的 Web 應用程式**：

1. 開啟 Lambda 主控台中的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇畫面右上角的圖示以開啟說明面板。  
![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/console_help_screenshot.png)

1. 選取**教學課程**。

1. 在**建立簡單的 Web 應用程式中**，選擇**開始教學課程**。

------
#### [ API Gateway ]

**使用下列資源開始使用 Lambda 和 API Gateway**
+ 依照教學課程[搭配使用 Lambda 與 API Gateway](services-apigateway-tutorial.md) 來建立與後端 Lambda 函數整合的 REST API。
+ 在 *Amazon API Gateway 開發人員指南*的下列章節中，進一步了解 API Gateway 提供的不同類型 API：
  + [API Gateway REST API](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-rest-api.html)
  + [API Gateway HTTP API](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api.html)
  + [API Gateway WebSocket API](https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-websocket-api.html)
+ 請嘗試 *Amazon API Gateway 開發人員指南*的[教學課程和研討會](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-tutorials.html)一節中的一個或多個範例。

------

# 教學課程：使用 Lambda 函式 URL 建立 Webhook 端點
<a name="urls-webhook-tutorial"></a>

在本教學課程中，您將建立 Lambda 函式 URL 來實作 Webhook 端點。Webhook 是一種輕量型的事件驅動型通訊機制，能透過 HTTP 自動在應用程式間傳輸資料。您可以使用 Webhook 來接收有關其他系統中發生事件的即時更新，例如當新客戶在網站上註冊、處理付款或上傳檔案時。

使用 Lambda 時，可以透過 Lambda 函式 URL 或 API Gateway 來實作 Webhook。對於不需要進階授權或請求驗證等功能的簡單 Webhook，函式 URL 是很好的選擇。

**提示**  
如果您不確定哪種解決方案最適合特定使用案例，請參閱[選取一種使用 HTTP 請求調用 Lambda 函數的方法](furls-http-invoke-decision.md)。

## 先決條件
<a name="urls-webhook-tutorial-prereqs"></a>

要完成本教學課程，必須在本機電腦上安裝 Python (3.8 版或更新版本) 或 Node.js (18 版或更新版本)。

為了使用 HTTP 請求測試端點，本教學課程使用了 [curl](https://curl.se/)。這是一個命令列工具，能透過多種網路通訊協定來傳輸資料。若尚未安裝此工具，請參閱 [curl 文件](https://curl.se/docs/install.html)了解安裝方法。

## 建立 Lambda 函式
<a name="urls-webhook-tutorial-function"></a>

首先建立當 HTTP 請求傳送至 Webhook 端點時執行的 Lambda 函式。在此範例中，傳送端應用程式會在付款提交時傳送更新，並在 HTTP 請求內文中指出付款是否成功。Lambda 函式會剖析請求，再依據付款狀態採取動作。在此範例中，程式碼僅會列印付款的訂單 ID，但在實際應用程式中，您可以將訂單新增至資料庫或傳送通知。

函式還實作了 Webhook 最常用的身分驗證方法，即雜湊訊息驗證碼 (HMAC)。使用此方法時，傳送端與接收端應用程式皆會共用一個秘密金鑰。傳送端應用程式使用雜湊演算法，利用此金鑰和訊息內容產生唯一簽章，並將該簽章作為 HTTP 標頭包含在 Webhook 請求中。然後，接收端應用程式會重複此步驟，使用秘密金鑰產生簽章，並將結果值與請求標頭中傳送的簽章進行比較。如果結果相符，請求會視為合法。

使用 Lambda 主控台並選擇 Python 或 Node.js 執行時期來建立函式。

------
#### [ Python ]

**建立 Lambda 函式**

1. 開啟 Lambda 主控台中的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 執行下列動作，建立基本的 'Hello world' 函式：

   1. 選擇 **Create function (建立函數)**。

   1. 選取**從頭開始撰寫**。

   1. 針對**函數名稱**，請輸入 **myLambdaWebhook**。

   1. 針對**執行期**，選取 **python3.14**。

   1. 選擇 **Create function (建立函數)**。

1. 在**程式碼來源**窗格中，複製並貼上以下項目來取代現有程式碼：

   ```
   import json
   import hmac
   import hashlib
   import os
   
   def lambda_handler(event, context):
       
       # Get the webhook secret from environment variables
       webhook_secret = os.environ['WEBHOOK_SECRET']
       
       # Verify the webhook signature
       if not verify_signature(event, webhook_secret):
           return {
               'statusCode': 401,
               'body': json.dumps({'error': 'Invalid signature'})
           }
       
       try:
           # Parse the webhook payload
           payload = json.loads(event['body'])
           
           # Handle different event types
           event_type = payload.get('type')
           
           if event_type == 'payment.success':
               # Handle successful payment
               order_id = payload.get('orderId')
               print(f"Processing successful payment for order {order_id}")
               
               # Add your business logic here
               # For example, update database, send notifications, etc.
               
           elif event_type == 'payment.failed':
               # Handle failed payment
               order_id = payload.get('orderId')
               print(f"Processing failed payment for order {order_id}")
               
               # Add your business logic here
               
           else:
               print(f"Received unhandled event type: {event_type}")
           
           # Return success response
           return {
               'statusCode': 200,
               'body': json.dumps({'received': True})
           }
           
       except json.JSONDecodeError:
           return {
               'statusCode': 400,
               'body': json.dumps({'error': 'Invalid JSON payload'})
           }
       except Exception as e:
           print(f"Error processing webhook: {e}")
           return {
               'statusCode': 500,
               'body': json.dumps({'error': 'Internal server error'})
           }
   
   def verify_signature(event, webhook_secret):
       """
       Verify the webhook signature using HMAC
       """
       try:
           # Get the signature from headers
           signature = event['headers'].get('x-webhook-signature')
   
           if not signature:
               print("Error: Missing webhook signature in headers")
               return False
           
           # Get the raw body (return an empty string if the body key doesn't exist)
           body = event.get('body', '')
           
           # Create HMAC using the secret key
           expected_signature = hmac.new(
               webhook_secret.encode('utf-8'),
               body.encode('utf-8'),
               hashlib.sha256
           ).hexdigest()
           
           # Compare the expected signature with the received signature to authenticate the message
           is_valid = hmac.compare_digest(signature, expected_signature)
           if not is_valid:
               print(f"Error: Invalid signature. Received: {signature}, Expected: {expected_signature}")
               return False
               
           return True
       except Exception as e:
           print(f"Error verifying signature: {e}")
           return False
   ```

1. 在 **DEPLOY** 區段中，選擇**部署**以更新函數的程式碼。

------
#### [ Node.js ]

**建立 Lambda 函式**

1. 開啟 Lambda 主控台中的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 執行下列動作，建立基本的 'Hello world' 函式：

   1. 選擇 **Create function (建立函數)**。

   1. 選取**從頭開始撰寫**。

   1. 針對**函數名稱**，請輸入 **myLambdaWebhook**。

   1. 針對**執行期**，選取 **nodejs24.x。**

   1. 選擇 **Create function (建立函數)**。

1. 在**程式碼來源**窗格中，複製並貼上以下項目來取代現有程式碼：

   ```
   import crypto from 'crypto';
   
   export const handler = async (event, context) => {
       // Get the webhook secret from environment variables
       const webhookSecret = process.env.WEBHOOK_SECRET;
   
       // Verify the webhook signature
       if (!verifySignature(event, webhookSecret)) {
           return {
               statusCode: 401,
               body: JSON.stringify({ error: 'Invalid signature' })
           };
       }
   
       try {
           // Parse the webhook payload
           const payload = JSON.parse(event.body);
   
           // Handle different event types
           const eventType = payload.type;
   
           switch (eventType) {
               case 'payment.success': {
                   // Handle successful payment
                   const orderId = payload.orderId;
                   console.log(`Processing successful payment for order ${orderId}`);
   
                   // Add your business logic here
                   // For example, update database, send notifications, etc.
                   break;
               }
   
               case 'payment.failed': {
                   // Handle failed payment
                   const orderId = payload.orderId;
                   console.log(`Processing failed payment for order ${orderId}`);
   
                   // Add your business logic here
                   break;
               }
   
               default:
                   console.log(`Received unhandled event type: ${eventType}`);
           }
   
           // Return success response
           return {
               statusCode: 200,
               body: JSON.stringify({ received: true })
           };
   
       } catch (error) {
           if (error instanceof SyntaxError) {
               // Handle JSON parsing errors
               return {
                   statusCode: 400,
                   body: JSON.stringify({ error: 'Invalid JSON payload' })
               };
           }
   
           // Handle all other errors
           console.error('Error processing webhook:', error);
           return {
               statusCode: 500,
               body: JSON.stringify({ error: 'Internal server error' })
           };
       }
   };
   
   // Verify the webhook signature using HMAC
   
   const verifySignature = (event, webhookSecret) => {
       try {
           // Get the signature from headers
           const signature = event.headers['x-webhook-signature'];
     
           if (!signature) {
               console.log('No signature found in headers:', event.headers);
               return false;
           }
     
           // Get the raw body (return an empty string if the body key doesn't exist)
           const body = event.body || '';
     
           // Create HMAC using the secret key
           const hmac = crypto.createHmac('sha256', webhookSecret);
           const expectedSignature = hmac.update(body).digest('hex');
     
           // Compare expected and received signatures
           const isValid = signature === expectedSignature;
           if (!isValid) {
               console.log(`Invalid signature. Received: ${signature}, Expected: ${expectedSignature}`);
               return false;
           }
           
           return true;
       } catch (error) {
           console.error('Error during signature verification:', error);
           return false;
       }
     };
   ```

1. 在 **DEPLOY** 區段中，選擇**部署**以更新函數的程式碼。

------

## 建立秘密金鑰
<a name="urls-webhook-tutorial-key"></a>

Lambda 函式若要驗證 Webhook 請求，會使用一個與呼叫應用程式共用的秘密金鑰。在此範例中，金鑰存放在環境變數中。但在生產應用程式中，請勿在函數程式碼中包含密碼等敏感資訊。反之，[請建立 AWS Secrets Manager 秘密](https://docs.aws.amazon.com/secretsmanager/latest/userguide/create_secret.html)，[然後使用 AWS 參數和秘密 Lambda 延伸](with-secrets-manager.md)來擷取 Lambda 函數中的登入資料。

**建立並儲存 Webhook 秘密金鑰**

1. 使用密碼編譯安全的隨機數字產生器，產生一個長的隨機字串。您可以使用下列以 Python 或 Node.js 編寫的程式碼片段來生成並列印 32 字元的秘密，也可以使用自己慣用的方法。

------
#### [ Python ]

**Example 產生秘密的程式碼**  

   ```
   import secrets
   webhook_secret = secrets.token_urlsafe(32)
   print(webhook_secret)
   ```

------
#### [ Node.js ]

**Example 產生秘密的程式碼 (ES 模組格式)**  

   ```
   import crypto from 'crypto';
   let webhookSecret = crypto.randomBytes(32).toString('base64');
   console.log(webhookSecret)
   ```

------

1. 執行下列動作，將產生的字串儲存為函式的環境變數：

   1. 在函式的**組態**索引標籤中，選取**環境變數**。

   1. 選擇**編輯**。

   1. 選擇 **Add environment variable** (新增環境變數)。

   1. 在**金鑰**欄位中，輸入 **WEBHOOK\$1SECRET**；接著在**值**欄位中，輸入上一個步驟中產生的秘密。

   1. 選擇**儲存**。

本教學課程後續將再次用到此金鑰來測試函式，因此請立即記錄下來。

## 建立函式 URL 端點
<a name="urls-webhook-tutorial-furl"></a>

使用 Lambda 函式 URL 為 Webhook 建立端點。由於您使用身分驗證類型 `NONE` 來建立具有公有存取權的端點，因此任何擁有 URL 的使用者都可以調用函式。若要進一步了解如何控制函式 URL 的存取權，請參閱[控制對 Lambda 函數 URL 的存取](urls-auth.md)。如果 Webhook 需要更進階的身分驗證選項，建議採用 API Gateway。

**建立函式 URL 端點**

1. 在函式的**組態**索引標籤中，選取**函式 URL**。

1. 選擇 **Create function URL** (建立函數 URL)。

1. 在**身分驗證類型**欄位中，選取 **NONE**。

1. 選擇**儲存**。

剛剛建立的函式 URL 端點會顯示在**函式 URL** 窗格中。複製端點，在教學課程後續部分使用。

## 在主控台中測試函式
<a name="urls-webhook-tutorial-test-console"></a>

在透過 URL 端點使用 HTTP 請求調用函式之前，請先在主控台中測試，確認程式碼如預期運作。

若要在主控台中驗證函式，需先使用之前在教學課程中產生的秘密，搭配以下測試用 JSON 承載資料計算 Webhook 簽章：

```
{
    "type": "payment.success", 
    "orderId": "1234",
    "amount": "99.99"
}
```

利用下列其中一個以 Python 或 Node.js 編寫的程式碼範例，並使用您自己的秘密來計算 Webhook 簽章。

------
#### [ Python ]

**計算 Webhook 簽章**

1. 將下列程式碼儲存為名為 `calculate_signature.py` 的檔案。將程式碼中的 Webhook 秘密取代為您自己的值。

   ```
   import secrets
   import hmac
   import json
   import hashlib
   
   webhook_secret = "arlbSDCP86n_1H90s0fL_Qb2NAHBIBQOyGI0X4Zay4M"
   
   body = json.dumps({"type": "payment.success", "orderId": "1234", "amount": "99.99"})
   
   signature = hmac.new(
               webhook_secret.encode('utf-8'),
               body.encode('utf-8'),
               hashlib.sha256
           ).hexdigest()
   
   print(signature)
   ```

1. 從儲存程式碼的同一目錄中執行下列命令來計算簽章。複製程式碼輸出的簽章。

   ```
   python calculate_signature.py
   ```

------
#### [ Node.js ]

**計算 Webhook 簽章**

1. 將下列程式碼儲存為名為 `calculate_signature.mjs` 的檔案。將程式碼中的 Webhook 秘密取代為您自己的值。

   ```
   import crypto from 'crypto';
   
   const webhookSecret = "arlbSDCP86n_1H90s0fL_Qb2NAHBIBQOyGI0X4Zay4M"
   const body = "{\"type\": \"payment.success\", \"orderId\": \"1234\", \"amount\": \"99.99\"}";
   
   let hmac = crypto.createHmac('sha256', webhookSecret);
   let signature = hmac.update(body).digest('hex');
   
   console.log(signature);
   ```

1. 從儲存程式碼的同一目錄中執行下列命令來計算簽章。複製程式碼輸出的簽章。

   ```
   node calculate_signature.mjs
   ```

------

現在，您可以在主控台中使用測試 HTTP 請求來測試函式程式碼。

**在主控台中測試函式**

1. 選取函式的**程式碼**索引標籤。

1. 在**測試事件**區段中，選擇**建立新測試事件**

1. **Event Name (事件名稱)** 輸入 **myEvent**。

1. 將下列項目複製並貼入**事件 JSON** 窗格中，取代現有的 JSON。將 Webhook 簽章取代為在上一個步驟中計算得出的值。

   ```
   {
     "headers": {
       "Content-Type": "application/json",
       "x-webhook-signature": "2d672e7a0423fab740fbc040e801d1241f2df32d2ffd8989617a599486553e2a"
     },
     "body": "{\"type\": \"payment.success\", \"orderId\": \"1234\", \"amount\": \"99.99\"}"
   }
   ```

1. 選擇**儲存**。

1. 選擇**調用**。

   您應該會看到類似下列的輸出：

------
#### [ Python ]

   ```
   Status: Succeeded
   Test Event Name: myEvent
   
   Response:
   {
     "statusCode": 200,
     "body": "{\"received\": true}"
   }
   
   Function Logs:
   START RequestId: 50cc0788-d70e-453a-9a22-ceaa210e8ac6 Version: $LATEST
   Processing successful payment for order 1234
   END RequestId: 50cc0788-d70e-453a-9a22-ceaa210e8ac6
   REPORT RequestId: 50cc0788-d70e-453a-9a22-ceaa210e8ac6	Duration: 1.55 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 36 MB	Init Duration: 136.32 ms
   ```

------
#### [ Node.js ]

   ```
   Status: Succeeded
   Test Event Name: myEvent
   
   Response:
   {
     "statusCode": 200,
     "body": "{\"received\":true}"
   }
   
   Function Logs:
   START RequestId: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4 Version: $LATEST
   2025-01-10T18:05:42.062Z	e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4	INFO	Processing successful payment for order 1234
   END RequestId: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4
   REPORT RequestId: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4	Duration: 60.10 ms	Billed Duration: 61 ms	Memory Size: 128 MB	Max Memory Used: 72 MB	Init Duration: 174.46 ms
   
   Request ID: e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4
   ```

------

## 使用 HTTP 請求測試函式
<a name="urls-webhook-tutorial-test-curl"></a>

使用 curl 命令列工具來測試 Webhook 端點。

**使用 HTTP 請求測試函式**

1. 在終端或 Shell 程式中，執行下列 curl 命令。將 URL 取代為您自己的函式 URL 端點的值，並將 Webhook 簽章取代為您使用自己的秘密金鑰計算得出的簽章。

   ```
   curl -X POST https://ryqgmbx5xjzxahif6frvzikpre0bpvpf.lambda-url.us-west-2.on.aws/ \
   -H "Content-Type: application/json" \
   -H "x-webhook-signature: d5f52b76ffba65ff60ea73da67bdf1fc5825d4db56b5d3ffa0b64b7cb85ef48b" \
   -d '{"type": "payment.success", "orderId": "1234", "amount": "99.99"}'
   ```

   您應該會看到下列輸出：

   ```
   {"received": true}
   ```

1. 執行下列動作，檢查函式的 CloudWatch 日誌，確認其正確剖析了承載：

   1. 在 Amazon CloudWatch 主控台中，開啟[日誌群組](https://console.aws.amazon.com/cloudwatch/home#logsV2:log-groups)頁面。

   1. 選取函式的日誌群組 (`/aws/lambda/myLambdaWebhook`)。

   1. 選取最新的日誌串流。

      您應該會在函式日誌中看到類似如下的輸出：

------
#### [ Python ]

      ```
      Processing successful payment for order 1234
      ```

------
#### [ Node.js ]

      ```
      2025-01-10T18:05:42.062Z e54fe6c7-1df9-4f05-a4c4-0f71cacd64f4 INFO Processing successful payment for order 1234
      ```

------

1. 執行下列 curl 命令，確認程式碼偵測到無效的簽章。將 URL 取代為您自己的函式 URL 端點。

   ```
   curl -X POST https://ryqgmbx5xjzxahif6frvzikpre0bpvpf.lambda-url.us-west-2.on.aws/ \
   -H "Content-Type: application/json" \
   -H "x-webhook-signature: abcdefg" \
   -d '{"type": "payment.success", "orderId": "1234", "amount": "99.99"}'
   ```

   您應該會看到下列輸出：

   ```
   {"error": "Invalid signature"}
   ```

## 清除您的資源
<a name="urls-webhook-tutorial-cleanup"></a>

除非您想要保留為此教學課程建立的資源，否則您現在便可刪除。透過刪除您不再使用 AWS 的資源，您可以避免不必要的 費用 AWS 帳戶。

**若要刪除 Lambda 函數**

1. 開啟 Lambda 主控台中的 [函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇您建立的函數。

1. 選擇 **Actions** (動作)、**Delete** (刪除)。

1. 在文字輸入欄位中輸入 **confirm**，然後選擇**刪除**。

當您在主控台中建立 Lambda 函式時，Lambda 也會為函式建立[執行角色](lambda-intro-execution-role.md)。

**刪除執行角色**

1. 開啟 IAM 主控台中的 [角色頁面](https://console.aws.amazon.com/iam/home#/roles) 。

1. 選取 Lambda 建立的執行角色。角色名稱具有格式 `myLambdaWebhook-role-<random string>`。

1. 選擇 **刪除**。

1. 在文字輸入欄位中輸入角色的名稱，然後選擇**刪除**。