

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

# 撰寫函數程式碼
<a name="writing-function-code"></a>

您可以使用 CloudFront Functions 撰寫 JavaScript 的輕量型函數，以進行高擴展性、對延遲敏感的 CDN 自訂。您的函數程式碼可以操作流經 CloudFront 的請求和回應，執行基本身分驗證和授權，在邊緣產生 HTTP 回應等。

為協助您為 CloudFront Functions 撰寫函數程式碼，請參閱下列主題。如需程式碼範例，請參閱 [CloudFront 的 CloudFront Functions 範例](service_code_examples_cloudfront_functions_examples.md) 和 GitHub 上的 [amazon-cloudfront-functions 儲存庫](https://github.com/aws-samples/amazon-cloudfront-functions)。

**Topics**
+ [

# 確定函數的用途
](function-code-choose-purpose.md)
+ [事件結構](functions-event-structure.md)
+ [JavaScript 執行時期功能](functions-javascript-runtime-features.md)
+ [

# 鍵值存放區的協助程式方法
](functions-custom-methods.md)
+ [

# 原始伺服器修改的 Helper 方法
](helper-functions-origin-modification.md)
+ [

# CloudFront SaaS Manager 屬性的 helper 方法
](saas-specific-logic-function-code.md)
+ [

# 使用 async 和 await
](async-await-syntax.md)
+ [

# CloudFront Functions 的 CWT 支援
](cwt-support-cloudfront-functions.md)
+ [

# 一般協助程式方法
](general-helper-methods.md)

# 確定函數的用途
<a name="function-code-choose-purpose"></a>

在撰寫函數程式碼之前，請先確定函數的用途。CloudFront Functions 中的大多數函數都具有以下用途之一。

**Topics**
+ [

## 修改檢視器請求事件類型中的 HTTP 請求
](#function-code-modify-request)
+ [

## 在檢視器請求事件類型中產生 HTTP 回應
](#function-code-generate-response)
+ [

## 在檢視者回應事件類型中修改 HTTP 回應
](#function-code-modify-response)
+ [

## 驗證連線請求事件類型的 mTLS 連線
](#function-code-connection-request)
+ [

## 相關資訊
](#related-information-cloudfront-functions-purpose)

無論函數的用途如何，`handler` 都是任何函數的入口點。它採用一個稱為 `event` 的參數，該參數由 CloudFront 傳遞給函數。`event` 是一個 JSON 對象，其中包含 HTTP 請求的表示 (以及回應，前提是您的函數修改了 HTTP 回應)。

## 修改檢視器請求事件類型中的 HTTP 請求
<a name="function-code-modify-request"></a>

您的函數可以修改 CloudFront 從檢視者 (用戶端) 接收的 HTTP 請求，並將修改後的請求返回給 CloudFront 以繼續處理。例如，您的函數程式碼可能會標準化[快取金鑰](understanding-the-cache-key.md)或修改請求標頭。

建立及發布修改 HTTP 請求的函數時，請務必新增*檢視器請求*事件類型的關聯。如需詳細資訊，請參閱[建立函數](functions-tutorial.md#functions-tutorial-create)。這會使 CloudFront 每次收到來自檢視器的請求時執行該函數，然後再檢視請求的物件是否位於 CloudFront 快取中。

**Example 範例**  
下面的虛擬程式碼顯示了修改 HTTP 請求的函數結構。  

```
function handler(event) {
    var request = event.request;

    // Modify the request object here.

    return request;
}
```
該函數將修改後的 `request` 物件返回到 CloudFront。CloudFront 會按如下方式繼續處理返回的請求：檢查 CloudFront 快取以取得快取命中率，並在必要時將請求傳送至來源。

## 在檢視器請求事件類型中產生 HTTP 回應
<a name="function-code-generate-response"></a>

您的函數可以在邊緣產生 HTTP 回應，並直接將其返回給檢視者 (用戶端)，而無需檢查快取的回應，也無需 CloudFront 進一步處理。例如，您的函數程式碼可能會將請求重新導向至新的 URL，或檢查授權並將 `401` 或 `403` 回應返回給未經授權的請求。

建立產生 HTTP 回應的函數時，請務必選擇*檢視者請求*事件類型。這表示 CloudFront 每次收到來自檢視者的請求時，該函數就會執行，然後 CloudFront 才進一步處理請求。

**Example 範例**  
下面的虛擬程式碼顯示了產生 HTTP 回應的函數結構。  

```
function handler(event) {
    var request = event.request;

    var response = ...; // Create the response object here,
                        // using the request properties if needed.

    return response;
}
```
該函數將 `response` 物件返回到 CloudFront，CloudFront 立即將其返回給檢視者，而無需檢查 CloudFront 快取或將請求傳送至來源。

## 在檢視者回應事件類型中修改 HTTP 回應
<a name="function-code-modify-response"></a>

您的函數可以在 CloudFront 將其發送給檢視者 (用戶端) 之前修改 HTTP 回應，無論該回應來自 CloudFront 快取還是來源。例如，您的函數代碼可能會新增或修改回應標頭、狀態碼，與本文內容。

建立可修改 HTTP 回應的函數時，請務必選擇*檢視者回應*事件類型。這表示無論回應是來自 CloudFront 快取還是來源，此函數都會在 CloudFront 將回應返回給檢視者之前執行。

**Example 範例**  
下面的虛擬程式碼顯示了修改 HTTP 回應的函數結構。  

```
function handler(event) {
    var request = event.request;
    var response = event.response;

    // Modify the response object here,
    // using the request properties if needed.

    return response;
}
```
該函數將修改後的 `response` 物件返回到 CloudFront，CloudFront 立即將其返回給檢視者。

## 驗證連線請求事件類型的 mTLS 連線
<a name="function-code-connection-request"></a>

連線函數是一種在 TLS 連線期間執行的 CloudFront 函數類型，可提供自訂驗證和身分驗證邏輯。連線函數目前可用於交互 TLS (mTLS) 連線，您可以在其中驗證用戶端憑證，並實作超出標準憑證驗證的自訂身分驗證邏輯。在 TLS 交握程序期間執行的連線函數，可以根據憑證屬性、用戶端 IP 地址或其他條件允許或拒絕連線。

在您建立和發佈連線函數之後，請務必新增*連線請求*事件類型的關聯與啟用 mTLS 的分佈。這可讓函數在每次用戶端嘗試與 CloudFront 建立 mTLS 連線時執行。

**Example**  
下列虛擬程式碼顯示連線函數的結構：  

```
function connectionHandler(connection) {
    // Validate certificate and connection properties here.
    
    if (/* validation passes */) {
        connection.allow();
    } else {
        connection.deny();
    }
}
```
函數使用協助程式方法來判斷是否允許或拒絕連線。與檢視器請求和檢視器回應函數不同，連線函數無法修改 HTTP 請求或回應。

## 相關資訊
<a name="related-information-cloudfront-functions-purpose"></a>

如需使用 CloudFront Functions 的詳細資訊，請參閱下列主題：
+ [事件結構](functions-event-structure.md)
+ [JavaScript 執行時期功能](functions-javascript-runtime-features.md)
+ [CloudFront Functions 範例 ](service_code_examples_cloudfront_functions_examples.md)
+ [對邊緣函數的限制](edge-functions-restrictions.md)

# CloudFront Functions 事件結構
<a name="functions-event-structure"></a>

CloudFront Functions 在運行該函數時將 `event` 物件作為輸入傳遞給您的函數程式碼。[測試函數](test-function.md)時，建立 `event` 物件並將其傳遞給函數。建立用於測試函數的 `event` 物件時，您可以省略 `distributionDomainName` 物件中的 `distributionId`、`requestId` 和 `context` 欄位。此外，請確保標頭名稱為小寫，CloudFront Functions 在生產期間傳遞給函數的 `event` 物件中也會始終採用此形式。

以下是此事件物件結構的概觀。

```
{
    "version": "1.0",
    "context": {
        <context object>
    },
    "viewer": {
        <viewer object>
    },
    "request": {
        <request object>
    },
    "response": {
        <response object>
    }
}
```

如需詳細資訊，請參閱下列主題：

**Topics**
+ [

## 版本欄位
](#functions-event-structure-version)
+ [

## 內容物件
](#functions-event-structure-context)
+ [

## 連線事件結構
](#functions-event-structure-connection)
+ [

## 檢視者物件
](#functions-event-structure-viewer)
+ [

## 請求物件
](#functions-event-structure-request)
+ [

## 回應物件
](#functions-event-structure-response)
+ [

## 狀態碼和本文
](#functions-event-structure-status-body)
+ [

## 查詢字串、標頭和 Cookie 的結構
](#functions-event-structure-query-header-cookie)
+ [

## 範例回應物件
](#functions-response-structure-example)
+ [

## 範例事件物件
](#functions-event-structure-example)

## 版本欄位
<a name="functions-event-structure-version"></a>

`version` 欄位包含指定 CloudFront Functions 事件物件版本的字串。目前版本是 `1.0`。

## 內容物件
<a name="functions-event-structure-context"></a>

`context` 物件包含有關事件的關聯式資訊。它包括以下欄位：

**`distributionDomainName`**  
與事件關聯之標準分佈的 CloudFront 網域名稱 (例如 d111111abcdef8.cloudfront.net)。  
只有在您的函數為標準分佈調用時，`distributionDomainName` 欄位才會出現。

**`endpoint`**  
與事件關聯之連線群組的 CloudFront 網域名稱 (例如 d111111abcdef8.cloudfront.net)。  
只有在您的函數為多租用戶分佈調用時，`endpoint` 欄位才會出現。

**`distributionId`**  
與事件相關聯的發佈的 ID (例如 EDFDVBD6EXAMPLE)。

**`eventType`**  
事件類型，`viewer-request` 或 `viewer-response`。

**`requestId`**  
唯一識別 CloudFront 請求 (及其相關回應) 的字串。

## 連線事件結構
<a name="functions-event-structure-connection"></a>

連線函數會收到與檢視器函數不同的事件結構。如需連線事件結構和回應格式的詳細資訊，請參閱 [關聯 CloudFront 連線函數](connection-functions.md)。

## 檢視者物件
<a name="functions-event-structure-viewer"></a>

`viewer` 物件包含一個 `ip` 欄位，其值是傳送請求的檢視者 (用戶端) 的 IP 位址。如果檢視者的請求來自 HTTP 代理或負載平衡器，此值為代理或負載平衡器的 IP 位址。

## 請求物件
<a name="functions-event-structure-request"></a>

`request` 物件包含檢視者到 CloudFront HTTP 請求的表示。在傳遞給函數的 `event` 物件中，`request` 物件代表 CloudFront 從檢視者接收的實際請求。

如果您的函數程式碼將 `request` 物件返回到 CloudFront，其必須使用相同的結構。

`request` 物件包含下列欄位：

**`method`**  
請求的 HTTP 方法。如果您的函數程式碼傳回 `request`，則無法修改此欄位。這是 `request` 物件中唯一的唯讀欄位。

**`uri`**  
請求物件的相對路徑。  
如果您的函數修改 `uri` 值，就適用下列事項：  
+ 全新的 `uri` 值必須以正斜線 (`/`) 作為開頭。
+ 當函數變更 `uri` 值時，它會變更檢視者請求的物件。
+ 當函數變更 `uri` 值時，它不會變更請求的快取行為或原始伺服器請求傳送的來源。

**`querystring`**  
代表請求中的查詢字串的物件。如果請求不包含查詢字串，`request` 物件仍會包含空白的 `querystring` 物件。  
`querystring` 物件針對請求中的每個查詢字串參數包含一個欄位。

**`headers`**  
代表請求中 HTTP 標頭的物件。如果請求包含任何 `Cookie` 標頭，則這些標頭不是 `headers` 物件的一部分。Cookies 在 `cookies` 物件中單獨表示。  
`headers` 物件針對請求中的每個標頭包含一個欄位。在事件物件中，標頭名稱會轉換為 ASCII 小寫，而在函數程式碼新增標頭名稱時，標頭名稱必須是 ASCII 小寫。CloudFront Functions 將事件物件轉換回 HTTP 請求時，標頭名稱中每個單字的第一個字母會大寫 (若為 ASCII 字母)。CloudFront Functions 不會將任何變更套用至標頭名稱中的非 ASCII 符號。例如 `TÈst-header` 將在函數內部變為 `tÈst-header`。非 ASCII 符號 `È` 保持不變。  
單字以連字號分隔 (`-`)。例如，如果函數程式碼新增名為 `example-header-name` 的標頭，CloudFront 會將其轉換為 HTTP 請求中的 `Example-Header-Name`。

**`cookies`**  
代表請求 (`Cookie` 標頭) 中 Cookie 的物件。  
`cookies` 物件針對請求中的每個 Cookie 包含一個欄位。

如需有關查詢字串、標頭和 Cookie 結構的詳細資訊，請參閱 [查詢字串、標頭和 Cookie 的結構](#functions-event-structure-query-header-cookie)。

如需範例 `event` 物件，請參閱 [範例事件物件](#functions-event-structure-example)。

## 回應物件
<a name="functions-event-structure-response"></a>

`response` 物件包含 CloudFront 到檢視者的 HTTP 回應的表示。在傳遞給函數的 `event` 物件中，`response` 物件代表 CloudFront 對檢視者請求的實際回應。

如果您的函數程式碼返回 `response` 物件，其必須使用相同的結構。

`response` 物件包含下列欄位：

**`statusCode`**  
回應的 HTTP 狀態碼。該值是一個整數，而不是字串。  
您的函數可以產生或修改 `statusCode`。

**`statusDescription`**  
回應的 HTTP 狀態說明。如果您的函數程式碼產生回應，則此欄位為選用。

**`headers`**  
代表回應中 HTTP 標頭的物件。如果回應包含任何 `Set-Cookie` 標頭，則這些標頭不是 `headers` 物件的一部分。Cookies 在 `cookies` 物件中單獨表示。  
`headers` 物件針對回應中的每個標頭包含一個欄位。在事件物件中，標頭名稱會轉換為小寫，而在函數程式碼新增標頭名稱時，標頭名稱必須是小寫。當 CloudFront Functions 將事件物件轉換回 HTTP 回應時，標頭名稱中每個單字的第一個字母會大寫。單字以連字號分隔 (`-`)。例如，如果函數程式碼新增名為 `example-header-name` 的標頭，CloudFront 會將其轉換為 HTTP 回應中的 `Example-Header-Name`。

**`cookies`**  
代表回應 (`Set-Cookie` 標頭) 中 Cookie 的物件。  
`cookies` 物件針對回應中的每個 Cookie 包含一個欄位。

**`body`**  
新增 `body` 欄位是選擇性的，除非您在函數中進行指定，否則它不會出現在 `response` 物件中。您的函數無法存取 CloudFront 快取或原始伺服器傳回的原始本文。如果您未在檢視器回應函數中指定 `body` 欄位，則 CloudFront 快取或原始伺服器回傳的原始本文將傳回給檢視器。  
如果您希望 CloudFront 將自訂本文傳回給檢視器，請在 `data` 欄位中指定本文內容，並在 `encoding` 欄位中指定本文編碼。您可以將編碼指定為純文字 (`"encoding": "text"`) 或 Base64 編碼的內容 (`"encoding": "base64"`)。  
作為捷徑，您也可以直接在 `body` 欄位 (`"body": "<specify the body content here>"`) 中指定本文內容。執行此操作時，請省略 `data` 和 `encoding` 欄位。在這種情況下，CloudFront 會將本文視為純文字。    
`encoding`  
`body` 內容 (`data` 欄位) 的編碼。唯一的有效編碼是 `text` 和 `base64`。  
如果您將 `encoding` 指定為 `base64` 但本文不是有效的 base64，CloudFront 會傳回錯誤。  
`data`  
`body` 內容。

如需有關已修改狀態碼和本文內容的更多資訊，請參閱 [狀態碼和本文](#functions-event-structure-status-body)。

如需有關標頭和 Cookie 結構的詳細資訊，請參閱 [查詢字串、標頭和 Cookie 的結構](#functions-event-structure-query-header-cookie)。

如需範例 `response` 物件，請參閱 [範例回應物件](#functions-response-structure-example)。

## 狀態碼和本文
<a name="functions-event-structure-status-body"></a>

透過 CloudFront Functions，您可以更新檢視者回應本文或將其移除。在評估來自 CloudFront 快取或原始伺服器回應的各個層面後，更新檢視器回應的一些常見案例包括：
+ 變更狀態以設定 HTTP 200 狀態碼並建立靜態本文內容，以傳回給檢視器。
+ 變更狀態以設定 HTTP 301 或 302 狀態碼來重新導向使用者到另一個網站。
+ 決定是否要提供或捨棄檢視者回應的本文。

**注意**  
如果原始伺服器傳回 400 及以上的 HTTP 錯誤，CloudFront Function 將無法執行。如需更多資訊，請參閱[對所有邊緣函數的限制](edge-function-restrictions-all.md)。

在您使用 HTTP 回應時，CloudFront Functions 將無法存取回應本文。您可以透過將本文內容設定為所需的值來進行替換，或設定為空值來移除本文。如果您不更新函數中的本文欄位，CloudFront 快取或原始伺服器回傳的原始本文會傳回給檢視器。

**提示**  
使用 CloudFront Functions 取代本文時，請務必將對應的標頭 (例如 `content-encoding`、`content-type` 或 `content-length`) 對齊新的本文內容。  
例如，如果 CloudFront 原始伺服器或快取傳回 `content-encoding: gzip`，但檢視器回應函數設定了純文字的本文，則該函數也需要相應變更 `content-encoding` 和 `content-type` 標頭。

如果您的 CloudFront Function 設定為傳回 400 或更高的 HTTP 錯誤，您的檢視者將不會看到您為相同狀態碼指定的[自訂錯誤頁面](creating-custom-error-pages.md)。

## 查詢字串、標頭和 Cookie 的結構
<a name="functions-event-structure-query-header-cookie"></a>

查詢字串、標頭和 Cookie 共用相同的結構。查詢字串可能會出現在請求中。標頭會出現在請求和回應中。Cookie 會出現在請求和回應中。

每個查詢字串、標頭或 Cookie 都是父系 `querystring`、`headers` 或 `cookies` 物件中的唯一欄位。欄位名稱是查詢字串、標頭或 Cookie 的名稱。每個欄位都包含具有查詢字串、標頭或 Cookie 值的 `value` 屬性。

**Contents**
+ [

### 查詢字串值或查詢字串物件
](#functions-event-structure-query)
+ [

### 標頭的特殊考量
](#functions-event-structure-headers)
+ [

### 重複的查詢字串、標頭和 Cookie (`multiValue` 陣列)
](#functions-event-structure-multivalue)
+ [

### Cookie 屬性
](#functions-event-structure-cookie-attributes)

### 查詢字串值或查詢字串物件
<a name="functions-event-structure-query"></a>

除了查詢字串物件之外，函數還可以傳回查詢字串值。查詢字串值可用來依任意自訂順序排列查詢字串參數。

**Example 範例**  
若要在函數程式碼中修改查詢字串，請使用如下所示的程式碼。  

```
var request = event.request; 
request.querystring = 'ID=42&Exp=1619740800&TTL=1440&NoValue=&querymv=val1&querymv=val2,val3';
```

### 標頭的特殊考量
<a name="functions-event-structure-headers"></a>

僅針對標頭，標頭名稱會在事件物件中轉換為小寫，而在函數程式碼新增標頭名稱時，標頭名稱則必須是小寫。當 CloudFront Functions 將事件物件轉換回 HTTP 請求或回應時，標頭名稱中每個單字的第一個字母會大寫。單字以連字號分隔 (`-`)。例如，如果函數程式碼新增名為 `example-header-name` 的標題，CloudFront 會將其轉換為 HTTP 請求或回應中的 `Example-Header-Name`。

**Example 範例**  
請考慮 HTTP 請求中的下列 `Host` 標頭。  

```
Host: video.example.com
```
此標頭在 `request` 物件中的表示方式如下：  

```
"headers": {
    "host": {
        "value": "video.example.com"
    }
}
```
若要在函數程式碼中存取 `Host` 標頭，請使用如下所示的程式碼：  

```
var request = event.request;
var host = request.headers.host.value;
```
若要在函數程式碼中新增或修改標頭，請使用如下所示的程式碼 (此程式碼會新增名為 `X-Custom-Header` 且包含值 `example value` 的標頭)：  

```
var request = event.request;
request.headers['x-custom-header'] = {value: 'example value'};
```

### 重複的查詢字串、標頭和 Cookie (`multiValue` 陣列)
<a name="functions-event-structure-multivalue"></a>

HTTP 請求或回應可以包含多個具有相同名稱的查詢字串、標頭或 Cookie。在此情況下，重複的查詢字串、標頭或 Cookie 會折疊成 `request` 或 `response` 物件中的一個欄位，但此欄位包含一個名為 `multiValue` 的額外屬性。`multiValue` 屬性包含一個陣列，其中帶有每個重複查詢字串、標頭或 Cookie 的值。

**Example 範例**  
請考慮包含下列 `Accept` 標頭的 HTTP 請求。  

```
Accept: application/json
Accept: application/xml
Accept: text/html
```
這些標頭在 `request` 物件中的表示方式如下。  

```
"headers": {
    "accept": {
        "value": "application/json",
        "multiValue": [
            {
                "value": "application/json"
            },
            {
                "value": "application/xml"
            },
            {
                "value": "text/html"
            }
        ]
    }
}
```

**注意**  
第一個標頭值 (在此情況為 `application/json`) 會在 `value` 和 `multiValue` 屬性中重複。這可讓您透過在 `multiValue` 陣列中執行迴圈來存取*所有*值。

如果您的函數程式碼修改具有 `multiValue` 陣列的查詢字串、標頭或 Cookie，CloudFront Functions 會使用下列規則來套用變更：

1. 如果 `multiValue` 陣列存在且有任何修改，則套用此修改。`value` 屬性中的第一個元素被忽略。

1. 否則，會套用 `value` 屬性的任何修改，並且後續的值 (如果存在) 保持不變。

只有當 HTTP 請求或回應包含具有相同名稱的重複查詢字串、標頭或 Cookie 時，才會使用 `multiValue` 屬性，如上述範例所示。但是，如果單一查詢字串、標頭或 Cookie 中有多個值，則不會使用該 `multiValue` 屬性。

**Example 範例**  
考慮具有一個 `Accept` 標頭的請求，而標頭中包含三個值。  

```
Accept: application/json, application/xml, text/html
```
此標頭在 `request` 物件中的表示方式如下。  

```
"headers": {
    "accept": {
        "value": "application/json, application/xml, text/html"
    }
}
```

### Cookie 屬性
<a name="functions-event-structure-cookie-attributes"></a>

在 HTTP 回應的 `Set-Cookie` 標頭中，標頭包含 Cookie 的名稱/值對，以及選用的一組屬性 (以分號分隔)。

**Example 範例**  

```
Set-Cookie: cookie1=val1; Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT
```
在 `response` 物件中，這些屬性會在 Cookie 欄位的 `attributes` 屬性中表示。例如，前面的 `Set-Cookie` 標頭表示如下：  

```
"cookie1": {
    "value": "val1",
    "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT"
}
```

## 範例回應物件
<a name="functions-response-structure-example"></a>

以下範例顯示一個本文已被檢視器回應函數替換的 `response` 物件 (檢視器回應函數的輸出)。

```
{
  "response": {
    "statusCode": 200,
    "statusDescription": "OK",
    "headers": {
      "date": {
        "value": "Mon, 04 Apr 2021 18:57:56 GMT"
      },
      "server": {
        "value": "gunicorn/19.9.0"
      },
      "access-control-allow-origin": {
        "value": "*"
      },
      "access-control-allow-credentials": {
        "value": "true"
      },
      "content-type": {
        "value": "text/html"
      },
      "content-length": {
        "value": "86"
      }
    },
    "cookies": {
      "ID": {
        "value": "id1234",
        "attributes": "Expires=Wed, 05 Apr 2021 07:28:00 GMT"
      },
      "Cookie1": {
        "value": "val1",
        "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT",
        "multiValue": [
          {
            "value": "val1",
            "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT"
          },
          {
            "value": "val2",
            "attributes": "Path=/cat; Domain=example.com; Expires=Wed, 10 Jan 2021 07:28:00 GMT"
          }
        ]
      }
    },
    
    // Adding the body field is optional and it will not be present in the response object
    // unless you specify it in your function.
    // Your function does not have access to the original body returned by the CloudFront
    // cache or origin.
    // If you don't specify the body field in your viewer response function, the original
    // body returned by the CloudFront cache or origin is returned to viewer.

     "body": {
      "encoding": "text",
      "data": "<!DOCTYPE html><html><body><p>Here is your custom content.</p></body></html>"
    }
  }
}
```

## 範例事件物件
<a name="functions-event-structure-example"></a>

以下範例顯示完整的 `event` 物件。這是標準分佈的範例調用，而不是多租用戶分佈。對於多租用戶分佈，會使用 `endpoint` 欄位而不是 `distributionDomainName`。`endpoint` 的值是與事件相關聯之連線群組的 CloudFront 網域名稱 (例如 d111111abcdef8.cloudfront.net)。

**注意**  
`event` 物件是函數的輸入。您的函數僅返回 `request` 或 `response` 物件，而不是完整的 `event` 物件。

```
{
    "version": "1.0",
    "context": {
        "distributionDomainName": "d111111abcdef8.cloudfront.net",
        "distributionId": "EDFDVBD6EXAMPLE",
        "eventType": "viewer-response",
        "requestId": "EXAMPLEntjQpEXAMPLE_SG5Z-EXAMPLEPmPfEXAMPLEu3EqEXAMPLE=="
    },
    "viewer": {"ip": "198.51.100.11"},
    "request": {
        "method": "GET",
        "uri": "/media/index.mpd",
        "querystring": {
            "ID": {"value": "42"},
            "Exp": {"value": "1619740800"},
            "TTL": {"value": "1440"},
            "NoValue": {"value": ""},
            "querymv": {
                "value": "val1",
                "multiValue": [
                    {"value": "val1"},
                    {"value": "val2,val3"}
                ]
            }
        },
        "headers": {
            "host": {"value": "video.example.com"},
            "user-agent": {"value": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:83.0) Gecko/20100101 Firefox/83.0"},
            "accept": {
                "value": "application/json",
                "multiValue": [
                    {"value": "application/json"},
                    {"value": "application/xml"},
                    {"value": "text/html"}
                ]
            },
            "accept-language": {"value": "en-GB,en;q=0.5"},
            "accept-encoding": {"value": "gzip, deflate, br"},
            "origin": {"value": "https://website.example.com"},
            "referer": {"value": "https://website.example.com/videos/12345678?action=play"},
            "cloudfront-viewer-country": {"value": "GB"}
        },
        "cookies": {
            "Cookie1": {"value": "value1"},
            "Cookie2": {"value": "value2"},
            "cookie_consent": {"value": "true"},
            "cookiemv": {
                "value": "value3",
                "multiValue": [
                    {"value": "value3"},
                    {"value": "value4"}
                ]
            }
        }
    },
    "response": {
        "statusCode": 200,
        "statusDescription": "OK",
        "headers": {
            "date": {"value": "Mon, 04 Apr 2021 18:57:56 GMT"},
            "server": {"value": "gunicorn/19.9.0"},
            "access-control-allow-origin": {"value": "*"},
            "access-control-allow-credentials": {"value": "true"},
            "content-type": {"value": "application/json"},
            "content-length": {"value": "701"}
        },
        "cookies": {
            "ID": {
                "value": "id1234",
                "attributes": "Expires=Wed, 05 Apr 2021 07:28:00 GMT"
            },
            "Cookie1": {
                "value": "val1",
                "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT",
                "multiValue": [
                    {
                        "value": "val1",
                        "attributes": "Secure; Path=/; Domain=example.com; Expires=Wed, 05 Apr 2021 07:28:00 GMT"
                    },
                    {
                        "value": "val2",
                        "attributes": "Path=/cat; Domain=example.com; Expires=Wed, 10 Jan 2021 07:28:00 GMT"
                    }
                ]
            }
        }
    }
}
```

# 適用於 CloudFront Functions 的 JavaScript 執行時期功能
<a name="functions-javascript-runtime-features"></a>

CloudFront Functions JavaScript 執行時期環境符合 [ECMAScript (ES) 版本 5.1](https://www.ecma-international.org/ecma-262/5.1/)，並且支援 ES 版本 6 到 12 的一些功能。

我們建議您使用 JavaScript 執行時期 2.0，以獲得最新功能。

相較於 1.0，JavaScript 執行時期 2.0 功能有下列變更：
+ 可使用緩衝區模組方法
+ 以下非標準字串原型方法無法使用：
  + `String.prototype.bytesFrom()`
  + `String.prototype.fromBytes()`
  + `String.prototype.fromUTF8()`
  + `String.prototype.toBytes()`
  + `String.prototype.toUTF8()`
+ 密碼編譯模組有以下變更：
  + `hash.digest()`：如果未提供編碼，則傳回類型變更為 `Buffer`
  + `hmac.digest()`：如果未提供編碼，則傳回類型變更為 `Buffer`
+ 如需其他新功能的詳細資訊，請參閱 [適用於 CloudFront Functions 的 JavaScript 執行時期 2.0 功能](functions-javascript-runtime-20.md)。

**Topics**
+ [JavaScript 執行時期 1.0 功能](functions-javascript-runtime-10.md)
+ [JavaScript 執行時期 2.0 功能](functions-javascript-runtime-20.md)

# 適用於 CloudFront Functions 的 JavaScript 執行時期 1.0 功能
<a name="functions-javascript-runtime-10"></a>

CloudFront Functions JavaScript 執行時期環境符合 [ECMAScript (ES) 版本 5.1](https://262.ecma-international.org/5.1/)，並且支援 ES 版本 6 到 9 的一些功能。它還提供了一些不屬於 ES 規格的非標準方法。

下列主題列出所有支援的語言功能。

**Topics**
+ [

## 核心功能
](#writing-functions-javascript-features-core)
+ [

## 基本物件
](#writing-functions-javascript-features-primitive-objects)
+ [

## 內建物件
](#writing-functions-javascript-features-builtin-objects)
+ [

## 錯誤類型
](#writing-functions-javascript-features-error-types)
+ [

## 全域變數
](#writing-functions-javascript-features-globals)
+ [

## 內建模組
](#writing-functions-javascript-features-builtin-modules)
+ [

## 限制功能
](#writing-functions-javascript-features-restricted-features)

## 核心功能
<a name="writing-functions-javascript-features-core"></a>

支援 ES 的以下核心功能。

**類型**  
支援所有 ES 5.1 類型。這包括布林值、數字、字串、物件、陣列、函數、函數建構子和常規表達式。

**運算子**  
支援所有 ES 5.1 運算子。  
支援 ES 7 指數運算子 (`**`)。

**聲明**  
不支援 `const` 和 `let` 陳述式。
支援下列 ES 5.1 陳述式：  
+ `break`
+ `catch`
+ `continue`
+ `do-while`
+ `else`
+ `finally`
+ `for`
+ `for-in`
+ `if`
+ `return`
+ `switch`
+ `throw`
+ `try`
+ `var`
+ `while`
+ 標記的陳述式

**文字**  
支援 ES 6 範本文字：多行字串、表達式插補和巢狀範本。

**函數**  
支援所有 ES 5.1 函數功能。  
支援 ES 6 箭頭函數，支援 ES 6 剩餘參數語法。

**Unicode**  
來源文字和字串常值可以包含 Unicode 編碼的字元。也支援由六個字元 (例如 `\uXXXX`) 組成的 Unicode 字碼指標逸出序列。

**嚴格模式**  
函數按預設會在嚴格模式下運作，因此您不需要在函數程式碼中新增 `use strict` 陳述式。無法對此進行變更。

## 基本物件
<a name="writing-functions-javascript-features-primitive-objects"></a>

支援 ES 的以下基本物件。

**物件**  
支援物件上的以下 ES 5.1 方法：  
+ `create`( 不含屬性清單)
+ `defineProperties`
+ `defineProperty`
+ `freeze`
+ `getOwnPropertyDescriptor`
+ `getOwnPropertyNames`
+ `getPrototypeOf`
+ `hasOwnProperty`
+ `isExtensible`
+ `isFrozen`
+ `prototype.isPrototypeOf`
+ `isSealed`
+ `keys`
+ `preventExtensions`
+ `prototype.propertyIsEnumerable`
+ `seal`
+ `prototype.toString`
+ `prototype.valueOf`
支援物件上的以下 ES 6 方法：  
+ `assign`
+ `is`
+ `prototype.setPrototypeOf`
支援物件上的以下 ES 8 方法：  
+ `entries`
+ `values`

**字串**  
支援以下針對字串的 ES 5.1 方法：  
+ `fromCharCode`
+ `prototype.charAt`
+ `prototype.concat`
+ `prototype.indexOf`
+ `prototype.lastIndexOf`
+ `prototype.match`
+ `prototype.replace`
+ `prototype.search`
+ `prototype.slice`
+ `prototype.split`
+ `prototype.substr`
+ `prototype.substring`
+ `prototype.toLowerCase`
+ `prototype.trim`
+ `prototype.toUpperCase`
支援字串上的以下 ES 6 方法：  
+ `fromCodePoint`
+ `prototype.codePointAt`
+ `prototype.endsWith`
+ `prototype.includes`
+ `prototype.repeat`
+ `prototype.startsWith`
支援字串上的以下 ES 8 方法：  
+ `prototype.padStart`
+ `prototype.padEnd`
支援字串上的以下 ES 9 方法：  
+ `prototype.trimStart`
+ `prototype.trimEnd`
支援字串上的以下非標準方法：  
+ `prototype.bytesFrom(array | string, encoding)`

  從八位元陣列或編碼字串建立一個位元組字串。字串編碼選項為 `hex`、`base64` 和 `base64url`。
+ `prototype.fromBytes(start[, end])`

  從位元組字串建立 Unicode 字串，其中每個位元組都會以對應的 Unicode 字碼指標取代。
+ `prototype.fromUTF8(start[, end])`

  從 UTF-8 編碼的位元組字串建立一個 Unicode 字串。如果編碼不正確，則返回 `null`。
+ `prototype.toBytes(start[, end])`

  從 Unicode 字串建立一個位元組字串。所有字元均必須在 [0,255] 範圍內。如果不在此範圍內，則返回 `null`。
+ `prototype.toUTF8(start[, end])`

  從一個 Unicode 字串建立一個 UTF-8 編碼的位元組字串。

**數字**  
支援數字上的所有 ES 5.1 方法。  
支援數字上的以下 ES 6 方法：  
+ `isFinite`
+ `isInteger`
+ `isNaN`
+ `isSafeInteger`
+ `parseFloat`
+ `parseInt`
+ `prototype.toExponential`
+ `prototype.toFixed`
+ `prototype.toPrecision`
+ `EPSILON`
+ `MAX_SAFE_INTEGER`
+ `MAX_VALUE`
+ `MIN_SAFE_INTEGER`
+ `MIN_VALUE`
+ `NEGATIVE_INFINITY`
+ `NaN`
+ `POSITIVE_INFINITY`

## 內建物件
<a name="writing-functions-javascript-features-builtin-objects"></a>

支援 ES 的以下內建物件。

**數學**  
支援所有 ES 5.1 數學方法。  
在 CloudFront Functions 執行時間環境中，`Math.random()` 實作會使用植入函數執行時間戳記的 OpenBSD `arc4random`。
支援以下 ES 6 數學方法：  
+ `acosh`
+ `asinh`
+ `atanh`
+ `cbrt`
+ `clz32`
+ `cosh`
+ `expm1`
+ `fround`
+ `hypot`
+ `imul`
+ `log10`
+ `log1p`
+ `log2`
+ `sign`
+ `sinh`
+ `tanh`
+ `trunc`
+ `E`
+ `LN10`
+ `LN2`
+ `LOG10E`
+ `LOG2E`
+ `PI`
+ `SQRT1_2`
+ `SQRT2`

**日期**  
支援所有 ES 5.1 `Date` 功能。  
基於安全考量，在單一函數執行的生命週期內，`Date` 始終返回相同的值 (函數的開始時間)。如需詳細資訊，請參閱 [限制功能](#writing-functions-javascript-features-restricted-features)。

**函數**  
支援 `apply`、`bind` 和 `call` 方法。  
不支援函數建構子。

**常規表達式**  
支援所有 ES 5.1 常規表達式功能。常規表達式語言與 Perl 相容。支援 ES 9 命名的擷取群組。

**JSON**  
支援所有 ES 5.1 JSON 功能，包括 `parse` 和 `stringify`。

**Array**  
支援陣列上的以下 ES 5.1 方法：  
+ `isArray`
+ `prototype.concat`
+ `prototype.every`
+ `prototype.filter`
+ `prototype.forEach`
+ `prototype.indexOf`
+ `prototype.join`
+ `prototype.lastIndexOf`
+ `prototype.map`
+ `prototype.pop`
+ `prototype.push`
+ `prototype.reduce`
+ `prototype.reduceRight`
+ `prototype.reverse`
+ `prototype.shift`
+ `prototype.slice`
+ `prototype.some`
+ `prototype.sort`
+ `prototype.splice`
+ `prototype.unshift`
支援陣列上的以下 ES 6 方法：  
+ `of`
+ `prototype.copyWithin`
+ `prototype.fill`
+ `prototype.find`
+ `prototype.findIndex`
支援陣列上的以下 ES 7 方法：  
+ `prototype.includes`

**類型陣列**  
支援以下 ES 6 類型陣列：  
+ `Int8Array`
+ `Uint8Array`
+ `Uint8ClampedArray`
+ `Int16Array`
+ `Uint16Array`
+ `Int32Array`
+ `Uint32Array`
+ `Float32Array`
+ `Float64Array`
+ `prototype.copyWithin`
+ `prototype.fill`
+ `prototype.join`
+ `prototype.set`
+ `prototype.slice`
+ `prototype.subarray`
+ `prototype.toString`

**陣列緩衝區**  
支援 `ArrayBuffer` 上的以下方法：  
+ `prototype.isView`
+ `prototype.slice`

**Promise**  
支援 Promise 上的以下方法：  
+ `reject`
+ `resolve`
+ `prototype.catch`
+ `prototype.finally`
+ `prototype.then`

**加密**  
密碼編譯模組提供標準雜湊和雜湊型訊息身分驗證碼 (HMAC) 協助程式。您可以使用 `require('crypto')` 加載模組。此模組會公開下列方法，其行為與 Node.js 對應方法完全相同：  
+ `createHash(algorithm)`
+ `hash.update(data)`
+ `hash.digest([encoding])`
+ `createHmac(algorithm, secret key)`
+ `hmac.update(data)`
+ `hmac.digest([encoding])`
如需詳細資訊，請參閱內建模組一節中的 [加密 (雜湊和 HMAC)](#writing-functions-javascript-features-builtin-modules-crypto)。

**主控台**  
這是一個用於偵錯的協助程式物件。它僅支援 `log()` 方法以記錄日誌訊息。  
CloudFront Functions 不支援逗號語法，例如 `console.log('a', 'b')`。因此請改為使用 `console.log('a' + ' ' + 'b')` 格式。

## 錯誤類型
<a name="writing-functions-javascript-features-error-types"></a>

支援以下錯誤物件：
+ `Error`
+ `EvalError`
+ `InternalError`
+ `MemoryError`
+ `RangeError`
+ `ReferenceError`
+ `SyntaxError`
+ `TypeError`
+ `URIError`

## 全域變數
<a name="writing-functions-javascript-features-globals"></a>

支援 `globalThis` 物件。

支援以下 ES 5.1 全局函數：
+ `decodeURI`
+ `decodeURIComponent`
+ `encodeURI`
+ `encodeURIComponent`
+ `isFinite`
+ `isNaN`
+ `parseFloat`
+ `parseInt`

支援以下全局常數：
+ `NaN`
+ `Infinity`
+ `undefined`

## 內建模組
<a name="writing-functions-javascript-features-builtin-modules"></a>

支援以下內建模組：

**Topics**
+ [

### 加密 (雜湊和 HMAC)
](#writing-functions-javascript-features-builtin-modules-crypto)
+ [

### 查詢字串
](#writing-functions-javascript-features-builtin-modules-query-string)

### 加密 (雜湊和 HMAC)
<a name="writing-functions-javascript-features-builtin-modules-crypto"></a>

密碼編譯模組 (`crypto`) 提供標準雜湊和雜湊型訊息身分驗證碼 (HMAC) 協助程式。您可以使用 `require('crypto')` 加載模組。此模組提供下列方法，其行為與 Node.js 對應方法完全相同：

**雜湊方法**

`crypto.createHash(algorithm)`  
建立並傳回雜湊物件，藉助此物件，您可以使用給定的演算法產生雜湊摘要：`md5`、`sha1` 或 `sha256`。

`hash.update(data)`  
使用給定的 `data` 更新雜湊內容。

`hash.digest([encoding])`  
計算使用 `hash.update()` 傳遞的所有資料的摘要。編碼可以是 `hex`、`base64` 或 `base64url`。

**HMAC 方法**

`crypto.createHmac(algorithm, secret key)`  
建立並返回使用給定 `algorithm` 和 `secret key` 的 HMAC 物件。演算法可以是 `md5`、`sha1` 或 `sha256`。

`hmac.update(data)`  
使用給定的 `data` 更新 HMAC 內容。

`hmac.digest([encoding])`  
計算使用 `hmac.update()` 傳遞的所有資料的摘要。編碼可以是 `hex`、`base64` 或 `base64url`。

### 查詢字串
<a name="writing-functions-javascript-features-builtin-modules-query-string"></a>

**注意**  
[CloudFront Functions 事件物件](functions-event-structure.md)會自動剖析 URL 查詢字串。這意味著在大多數情況下，您不需要使用此模組。

查詢字串模組 (`querystring`) 提供剖析和格式化 URL 查詢字串的方法。您可以使用 `require('querystring')` 加載模組。此模組提供下列方法。

`querystring.escape(string)`  
URL 編碼給定的 `string`，傳回逸出的查詢字串。該方法由 `querystring.stringify()` 使用，並且不應直接使用。

`querystring.parse(string[, separator[, equal[, options]]])`  
剖析查詢字串 (`string`) 並傳回物件。  
`separator` 參數是用來分隔查詢字串中的鍵/值對的子字串。其在預設情況下為 `&`。  
`equal` 參數是用來分隔查詢字串中的鍵和值的子字串。其在預設情況下為 `=`。  
`options` 參數是具有下列鍵的物件：    
`decodeURIComponent function`  
解碼查詢字串中百分比編碼字元的函數。其在預設情況下為 `querystring.unescape()`。  
`maxKeys number`  
要剖析的鍵的最大數量。其在預設情況下為 `1000`。使用 `0` 的值移除計數鍵的限制。
根據預設，查詢字串中的百分比編碼字元會假設為使用 UTF-8 編碼。無效的 UTF-8 序列會被取代為 `U+FFFD` 取代字元。  
例如，對於下列查詢字串：  

```
'name=value&abc=xyz&abc=123'
```
`querystring.parse()` 的返回值是：  

```
{
name: 'value',
abc: ['xyz', '123']
}
```
`querystring.decode()` 是 的別名。`querystring.parse()`

`querystring.stringify(object[, separator[, equal[, options]]])`  
序列化 `object` 並傳回查詢字串。  
`separator` 參數是用來分隔查詢字串中的鍵/值對的子字串。其在預設情況下為 `&`。  
`equal` 參數是用來分隔查詢字串中的鍵和值的子字串。其在預設情況下為 `=`。  
`options` 參數是具有下列鍵的物件：    
`encodeURIComponent function`  
用於將 URL 不安全字元轉換為查詢字串中的百分比編碼的函數。其在預設情況下為 `querystring.escape()`。
根據預設，在查詢字串中需要百分比編碼的字元會編碼為 UTF-8。若要使用不同的編碼，請指定 `encodeURIComponent` 選項。  
例如，對於以下程式碼：  

```
querystring.stringify({ name: 'value', abc: ['xyz', '123'], anotherName: '' });
```
返回值是：  

```
'name=value&abc=xyz&abc=123&anotherName='
```
`querystring.encode()` 是 `querystring.stringify()` 的別名。

`querystring.unescape(string)`  
解碼給定 `string` 中的 URL 百分比編碼字元，傳回未逸出的查詢字串。此方法由 `querystring.parse()` 使用，並且不應直接使用。

## 限制功能
<a name="writing-functions-javascript-features-restricted-features"></a>

由於安全考量，下列 JavaScript 語言功能不受支援或受到限制。

**動態程式碼評估**  
不支援動態程式碼評估。如果嘗試此評估，`eval()` 和 `Function` 建構子都會丟出錯誤。例如，`const sum = new Function('a', 'b', 'return a + b')` 丟出錯誤。

**計時器**  
不支援 `setTimeout()`、`setImmediate()` 和 `clearTimeout()` 函數。在函數執行時期間未推遲或產生任何佈建。您的函數必須同步執行方可完成。

**日期和時間戳記**  
基於安全考量，無法存取高解析度計時器。查詢當前時間的所有 `Date` 方法始終在單個函數執行的生命週期內返回相同的值。返回的時間戳記是函數開始執行的時間。因此，您無法測量函數中的經過時間。

**檔案系統存取**  
沒有檔案系統存取權。例如，沒有類似 Node.js 中的檔案系統存取 `fs` 模組。

**處理存取**  
沒有處理存取。例如沒有 `process` 全域物件可像 Node.js 一樣處理資訊存取。

**環境變數**  
無法存取環境變數。  
您可以改為使用 CloudFront KeyValueStore 為您的 CloudFront Functions 建立鍵值對的集中式資料儲存。CloudFront KeyValueStore 可動態更新組態資料，不需要部署程式碼變更。您必須使用 [JavaScript 執行時期 2.0](functions-javascript-runtime-20.md)，才能使用 CloudFront KeyValueStore。如需詳細資訊，請參閱[Amazon CloudFront KeyValueStore](kvs-with-functions.md)。

**網路存取**  
不支援網路呼叫。例如，不支援 XHR、HTTP(S) 和通訊端。

# 適用於 CloudFront Functions 的 JavaScript 執行時期 2.0 功能
<a name="functions-javascript-runtime-20"></a>

CloudFront Functions JavaScript 執行時期環境符合 [ECMAScript (ES) 版本 5.1](https://262.ecma-international.org/5.1/)，並且支援 ES 版本 6 到 12 的一些功能。它還提供了一些不屬於 ES 規格的非標準方法。以下主題列出此執行時期支援的所有功能。

**Topics**
+ [

## 核心功能
](#writing-functions-javascript-features-core-20)
+ [

## 基本物件
](#writing-functions-javascript-features-primitive-objects-20)
+ [

## 內建物件
](#writing-functions-javascript-features-builtin-objects-20)
+ [

## 錯誤類型
](#writing-functions-javascript-features-error-types-20)
+ [

## 全域變數
](#writing-functions-javascript-features-globals-20)
+ [

## 內建模組
](#writing-functions-javascript-features-builtin-modules-20)
+ [

## 限制功能
](#writing-functions-javascript-features-restricted-features-20)

## 核心功能
<a name="writing-functions-javascript-features-core-20"></a>

支援 ES 的以下核心功能。

**類型**  
支援所有 ES 5.1 類型。這包括布林值、數字、字串、物件、陣列、函數和常規表達式。

**運算子**  
支援所有 ES 5.1 運算子。  
支援 ES 7 指數運算子 (`**`)。

**陳述式**  
支援下列 ES 5.1 陳述式：  
+ `break`
+ `catch`
+ `continue`
+ `do-while`
+ `else`
+ `finally`
+ `for`
+ `for-in`
+ `if`
+ `label`
+ `return`
+ `switch`
+ `throw`
+ `try`
+ `var`
+ `while`
支援以下 ES 6 陳述式：  
+ `const`
+ `let`
支援下列 ES 8 陳述式：  
+ `async`
+ `await`
`async`、`await`、`const` 和 `let` 是 JavaScript 執行時期 2.0 支援的功能。  
`await` 只能在 `async` 函數內使用，不支援 `async` 引數和關閉。

**文字**  
支援 ES 6 範本文字：多行字串、表達式插補和巢狀範本。

**函數**  
支援所有 ES 5.1 函數功能。  
支援 ES 6 箭頭函數，支援 ES 6 剩餘參數語法。

**Unicode**  
來源文字和字串常值可以包含 Unicode 編碼的字元。也支援由六個字元 (例如 `\uXXXX`) 組成的 Unicode 字碼指標逸出序列。

**嚴格模式**  
函數按預設會在嚴格模式下運作，因此您不需要在函數程式碼中新增 `use strict` 陳述式。無法對此進行變更。

## 基本物件
<a name="writing-functions-javascript-features-primitive-objects-20"></a>

支援 ES 的以下基本物件。

**物件**  
支援物件上的以下 ES 5.1 方法：  
+ `Object.create()`( 不含屬性清單)
+ `Object.defineProperties()`
+ `Object.defineProperty()`
+ `Object.freeze()`
+ `Object.getOwnPropertyDescriptor()`
+ `Object.getOwnPropertyDescriptors()`
+ `Object.getOwnPropertyNames()`
+ `Object.getPrototypeOf()`
+ `Object.isExtensible()`
+ `Object.isFrozen()`
+ `Object.isSealed()`
+ `Object.keys()`
+ `Object.preventExtensions()`
+ `Object.seal()`
支援物件上的以下 ES 6 方法：  
+ `Object.assign()`
支援物件上的以下 ES 8 方法：  
+ `Object.entries()`
+ `Object.values()`
支援以下針對物件的 ES 5.1 原型方法：  
+ `Object.prototype.hasOwnProperty()`
+ `Object.prototype.isPrototypeOf()`
+ `Object.prototype.propertyIsEnumerable()`
+ `Object.prototype.toString()`
+ `Object.prototype.valueOf()`
支援以下針對物件的 ES 6 原型方法：  
+ `Object.prototype.is()`
+ `Object.prototype.setPrototypeOf()`

**String**  
支援以下針對字串的 ES 5.1 方法：  
+ `String.fromCharCode()`
支援以下針對字串的 ES 6 方法：  
+ `String.fromCodePoint()`
支援以下針對字串的 ES 5.1 原型方法：  
+ `String.prototype.charAt()`
+ `String.prototype.concat()`
+ `String.prototype.indexOf()`
+ `String.prototype.lastIndexOf()`
+ `String.prototype.match()`
+ `String.prototype.replace()`
+ `String.prototype.search()`
+ `String.prototype.slice()`
+ `String.prototype.split()`
+ `String.prototype.substr()`
+ `String.prototype.substring()`
+ `String.prototype.toLowerCase()`
+ `String.prototype.trim()`
+ `String.prototype.toUpperCase()`
支援以下針對字串的 ES 6 原型方法：  
+ `String.prototype.codePointAt()`
+ `String.prototype.endsWith()`
+ `String.prototype.includes()`
+ `String.prototype.repeat()`
+ `String.prototype.startsWith()`
支援以下針對字串的 ES 8 原型方法：  
+ `String.prototype.padStart()`
+ `String.prototype.padEnd()`
支援以下針對字串的 ES 9 原型方法：  
+ `String.prototype.trimStart()`
+ `String.prototype.trimEnd()`
支援以下針對字串的 ES 12 原型方法：  
+ `String.prototype.replaceAll()`
**注意**  
`String.prototype.replaceAll()` 是 JavaScript 執行時間 2.0 的新功能。

**Number**  
支援所有 ES 5 數字。  
支援以下 ES 6 數字屬性：  
+ `Number.EPSILON`
+ `Number.MAX_SAFE_INTEGER`
+ `Number.MIN_SAFE_INTEGER`
+ `Number.MAX_VALUE`
+ `Number.MIN_VALUE`
+ `Number.NaN`
+ `Number.NEGATIVE_INFINITY`
+ `Number.POSITIVE_INFINITY`
支援數字上的以下 ES 6 方法：  
+ `Number.isFinite()`
+ `Number.isInteger()`
+ `Number.isNaN()`
+ `Number.isSafeInteger()`
+ `Number.parseInt()`
+ `Number.parseFloat()`
支援以下針對數字的 ES 5.1 原型方法：  
+ `Number.prototype.toExponential()`
+ `Number.prototype.toFixed()`
+ `Number.prototype.toPrecision()`
支援 ES 12 數字分隔符號。  
ES 12 數字分隔符號是 JavaScript 執行時間 2.0 的新功能。

## 內建物件
<a name="writing-functions-javascript-features-builtin-objects-20"></a>

支援 ES 的以下內建物件。

**數學**  
支援所有 ES 5.1 數學方法。  
在 CloudFront Functions 執行時間環境中，`Math.random()` 實作會使用植入函數執行時間戳記的 OpenBSD `arc4random`。
支援以下 ES 6 數學屬性：  
+ `Math.E`
+ `Math.LN10`
+ `Math.LN2`
+ `Math.LOG10E`
+ `Math.LOG2E`
+ `Math.PI`
+ `Math.SQRT1_2`
+ `Math.SQRT2`
支援以下 ES 6 數學方法：  
+ `Math.abs()`
+ `Math.acos()`
+ `Math.acosh()`
+ `Math.asin()`
+ `Math.asinh()`
+ `Math.atan()`
+ `Math.atan2()`
+ `Math.atanh()`
+ `Math.cbrt()`
+ `Math.ceil()`
+ `Math.clz32()`
+ `Math.cos()`
+ `Math.cosh()`
+ `Math.exp()`
+ `Math.expm1()`
+ `Math.floor()`
+ `Math.fround()`
+ `Math.hypot()`
+ `Math.imul()`
+ `Math.log()`
+ `Math.log1p()`
+ `Math.log2()`
+ `Math.log10()`
+ `Math.max()`
+ `Math.min()`
+ `Math.pow()`
+ `Math.random()`
+ `Math.round()`
+ `Math.sign()`
+ `Math.sinh()`
+ `Math.sin()`
+ `Math.sqrt()`
+ `Math.tan()`
+ `Math.tanh()`
+ `Math.trunc()`

**日期**  
支援所有 ES 5.1 `Date` 功能。  
基於安全考量，在單一函數執行的生命週期內，`Date` 始終返回相同的值 (函數的開始時間)。如需詳細資訊，請參閱 [限制功能](functions-javascript-runtime-10.md#writing-functions-javascript-features-restricted-features)。

**函數**  
支援以下 ES 5.1 原型方法：  
+ `Function.prototype.apply()`
+ `Function.prototype.bind()`
+ `Function.prototype.call()`
不支援函數建構子。

**常規表達式**  
支援所有 ES 5.1 常規表達式功能。常規表達式語言與 Perl 相容。  
支援以下 ES 5.1 原型存取子屬性：  
+ `RegExp.prototype.global`
+ `RegExp.prototype.ignoreCase`
+ `RegExp.protoype.multiline`
+ `RegExp.protoype.source`
+ `RegExp.prototype.sticky`
+ `RegExp.prototype.flags`
**注意**  
`RegExp.prototype.sticky` 和 `RegExp.prototype.flags` 是 JavaScript 執行時間 2.0 的新功能。
支援以下 ES 5.1 原型方法：  
+ `RegExp.prototype.exec()`
+ `RegExp.prototype.test()`
+ `RegExp.prototype.toString()`
+ `RegExp.prototype[@@replace]()`
+ `RegExp.prototype[@@split]()`
**注意**  
`RegExp.prototype[@@split]()` 是 JavaScript 執行時間 2.0 的新功能。
支援以下 ES 5.1 執行個體屬性：  
+ `lastIndex`
支援 ES 9 命名的擷取群組。

**JSON**  
支援以下 ES 5.1 方法：  
+ `JSON.parse()`
+ `JSON.stringify()`

**陣列**  
支援陣列上的以下 ES 5.1 方法：  
+ `Array.isArray()`
支援陣列上的以下 ES 6 方法：  
+ `Array.of()`
支援以下 ES 5.1 原型方法：  
+ `Array.prototype.concat()`
+ `Array.prototype.every()`
+ `Array.prototype.filter()`
+ `Array.prototype.forEach()`
+ `Array.prototype.indexOf()`
+ `Array.prototype.join()`
+ `Array.prototype.lastIndexOf()`
+ `Array.prototype.map()`
+ `Array.prototype.pop()`
+ `Array.prototype.push()`
+ `Array.prototype.reduce()`
+ `Array.prototype.reduceRight()`
+ `Array.prototype.reverse()`
+ `Array.prototype.shift()`
+ `Array.prototype.slice()`
+ `Array.prototype.some()`
+ `Array.prototype.sort()`
+ `Array.prototype.splice()`
+ `Array.prototype.unshift()`
支援以下 ES 6 原型方法  
+ `Array.prototype.copyWithin()`
+ `Array.prototype.fill()`
+ `Array.prototype.find()`
+ `Array.prototype.findIndex()`
支援以下 ES 7 原型方法：  
+ `Array.prototype.includes()`

**類型陣列**  
支援以下 ES 6 類型陣列建構子：  
+ `Float32Array`
+ `Float64Array`
+ `Int8Array`
+ `Int16Array`
+ `Int32Array`
+ `Uint8Array`
+ `Uint8ClampedArray`
+ `Uint16Array`
+ `Uint32Array`
支援以下 ES 6 方法：  
+ `TypedArray.from()`
+ `TypedArray.of()`
**注意**  
`TypedArray.from()` 和 `TypedArray.of()` 是 JavaScript 執行時間 2.0 的新功能。
支援以下 ES 6 原型方法：  
+ `TypedArray.prototype.copyWithin()`
+ `TypedArray.prototype.every()`
+ `TypedArray.prototype.fill()`
+ `TypedArray.prototype.filter()`
+ `TypedArray.prototype.find()`
+ `TypedArray.prototype.findIndex()`
+ `TypedArray.prototype.forEach()`
+ `TypedArray.prototype.includes()`
+ `TypedArray.prototype.indexOf()`
+ `TypedArray.prototype.join()`
+ `TypedArray.prototype.lastIndexOf()`
+ `TypedArray.prototype.map()`
+ `TypedArray.prototype.reduce()`
+ `TypedArray.prototype.reduceRight()`
+ `TypedArray.prototype.reverse()`
+ `TypedArray.prototype.some()`
+ `TypedArray.prototype.set()`
+ `TypedArray.prototype.slice()`
+ `TypedArray.prototype.sort()`
+ `TypedArray.prototype.subarray()`
+ `TypedArray.prototype.toString()`
**注意**  
`TypedArray.prototype.every()`、`TypedArray.prototype.fill()`、`TypedArray.prototype.filter()`、`TypedArray.prototype.find()`、`TypedArray.prototype.findIndex()`、`TypedArray.prototype.forEach()`、`TypedArray.prototype.includes()`、`TypedArray.prototype.indexOf()`、`TypedArray.prototype.join()`、`TypedArray.prototype.lastIndexOf()`、`TypedArray.prototype.map()`、`TypedArray.prototype.reduce()`、`TypedArray.prototype.reduceRight()`、`TypedArray.prototype.reverse()` 和 `TypedArray.prototype.some()` 是 JavaScript 執行時間 2.0 的新功能。

**ArrayBuffer**  
支援以下針對 ArrayBuffer 的 ES 6 方法：  
+ `isView()`
支援以下針對 ArrayBuffer 的 ES 6 原型方法：  
+ `ArrayBuffer.prototype.slice()`

**Promise**  
支援以下針對 Promise 的 ES 6 方法：  
+ `Promise.all()`
+ `Promise.allSettled()`
+ `Promise.any()`
+ `Promise.reject()`
+ `Promise.resolve()`
+ `Promise.race()`
**注意**  
`Promise.all()`、`Promise.allSettled()`、`Promise.any()` 和 `Promise.race()` 是 JavaScript 執行時間 2.0 的新功能。
支援以下針對 Promise 的 ES 6 原型方法：  
+ `Promise.prototype.catch()`
+ `Promise.prototype.finally()`
+ `Promise.prototype.then()`

**DataView**  
支援以下 ES 6 原型方法：  
+ `DataView.prototype.getFloat32()`
+ `DataView.prototype.getFloat64()`
+ `DataView.prototype.getInt16()`
+ `DataView.prototype.getInt32()`
+ `DataView.prototype.getInt8()`
+ `DataView.prototype.getUint16()`
+ `DataView.prototype.getUint32()`
+ `DataView.prototype.getUint8()`
+ `DataView.prototype.setFloat32()`
+ `DataView.prototype.setFloat64()`
+ `DataView.prototype.setInt16()`
+ `DataView.prototype.setInt32()`
+ `DataView.prototype.setInt8()`
+ `DataView.prototype.setUint16()`
+ `DataView.prototype.setUint32()`
+ `DataView.prototype.setUint8()`
**注意**  
所有 DataView ES 6 原型方法都是 JavaScript 執行時間 2.0 的新功能。

**Symbol**  
支援以下 ES 6 方法：  
+ `Symbol.for()`
+ `Symbol.keyfor()`
**注意**  
所有符號 ES 6 方法都是 JavaScript 執行時間 2.0 的新功能。

**文字解碼器**  
支援以下原型方法：  
+ `TextDecoder.prototype.decode()`
支援以下原型存取子屬性：  
+ `TextDecoder.prototype.encoding`
+ `TextDecoder.prototype.fatal`
+ `TextDecoder.prototype.ignoreBOM`

**文字編碼器**  
支援以下原型方法：  
+ `TextEncoder.prototype.encode()`
+ `TextEncoder.prototype.encodeInto()`

**主控台**  
這是一個用於偵錯的協助程式物件。它僅支援 `log()` 方法以記錄日誌訊息。  
CloudFront Functions 不支援逗號語法，例如 `console.log('a', 'b')`。因此請改為使用 `console.log('a' + ' ' + 'b')` 格式。

## 錯誤類型
<a name="writing-functions-javascript-features-error-types-20"></a>

支援以下錯誤物件：
+ `Error`
+ `EvalError`
+ `InternalError`
+ `RangeError`
+ `ReferenceError`
+ `SyntaxError`
+ `TypeError`
+ `URIError`

## 全域變數
<a name="writing-functions-javascript-features-globals-20"></a>

支援 `globalThis` 物件。

支援以下 ES 5.1 全局函數：
+ `decodeURI()`
+ `decodeURIComponent()`
+ `encodeURI()`
+ `encodeURIComponent()`
+ `isFinite()`
+ `isNaN()`
+ `parseFloat()`
+ `parseInt()`

支援以下 ES 6 全域函數：
+ `atob()`
+ `btoa()`
**注意**  
`atob()` 和 `btoa()` 是 JavaScript 執行時間 2.0 的新功能。

支援以下全局常數：
+ `NaN`
+ `Infinity`
+ `undefined`
+ `arguments`

## 內建模組
<a name="writing-functions-javascript-features-builtin-modules-20"></a>

支援以下內建模組：

**Topics**
+ [

### 緩衝區
](#writing-functions-javascript-features-builtin-modules-buffer-20)
+ [

### 查詢字串
](#writing-functions-javascript-features-builtin-modules-query-string-20)
+ [

### 加密
](#writing-functions-javascript-features-builtin-modules-crypto-20)

### 緩衝區
<a name="writing-functions-javascript-features-builtin-modules-buffer-20"></a>

此模組提供以下方法：
+ `Buffer.alloc(size[, fill[, encoding]])`

  配置 `Buffer`。
  + `size`：緩衝區大小。輸入整數。
  + `fill`：選用。輸入字串、`Buffer`、Uint8Array 或整數。預設值為 `0`。
  + `encoding`：選用。當 `fill` 為字串，請輸入以下其中一項：`utf8`、`hex`、`base64`、`base64url`。預設值為 `utf8`。
+ `Buffer.allocUnsafe(size)`

  配置一個未初始化的 `Buffer`。
  + `size`：輸入整數。
+ `Buffer.byteLength(value[, encoding])`

  返回值的長度，以位元組為單位。
  + `value`: 字串、`Buffer`、TypedArray、DataView 或 ArrayBuffer。
  + `encoding`：選用。當 `value` 為字串，請輸入以下其中一項：`utf8`、`hex`、`base64`、`base64url`。預設值為 `utf8`。
+ `Buffer.compare(buffer1, buffer2)`

  比較兩個 `Buffer` 以協助對陣列進行排序。如果兩者相同則傳回 `0`，如果 `buffer1` 在前面則傳回 `-1`，或如果 `buffer2` 在前面則傳回 `1`。
  + `buffer1`：輸入 `Buffer`。
  + `buffer2`：輸入不同的 `Buffer`。
+ `Buffer.concat(list[, totalLength])`

  連接多個 `Buffer`。如果沒有則傳回 `0`。最多傳回 `totalLength`。
  + `list`：輸入 `Buffer` 的清單。請注意，這將被截斷為 `totalLength`。
  + `totalLength`：選用。輸入不帶正負號的整數。如果清單為空白，則使用清單中 `Buffer` 執行個體的總和。
+ `Buffer.from(array)`

  從陣列建立 `Buffer`。
  + `array`: 輸入從 `0` 到 `255` 的位元組陣列。
+ `Buffer.from(arrayBuffer, byteOffset[, length]))`

  從 `arrayBuffer` 建立檢視，從偏移值 `byteOffset` 開始，長度為 `length`。
  + `arrayBuffer`：輸入 `Buffer` 陣列。
  + `byteOffset`：輸入整數。
  + `length`：選用。輸入整數。
+ `Buffer.from(buffer)`

  建立 `Buffer` 的複本。
  + `buffer`：輸入 `Buffer`。
+ `Buffer.from(object[, offsetOrEncoding[, length]])`

  從物件建立 `Buffer`。如果 `valueOf()` 不等於物件，則傳回 `Buffer.from(object.valueOf(), offsetOrEncoding, length)`。
  + `object`：輸入物件。
  + `offsetOrEncoding`：選用。輸入整數或編碼字串。
  + `length`：選用。輸入整數。
+ `Buffer.from(string[, encoding])`

  從字串建立一個 `Buffer`。
  + `string`：輸入字串。
  + `encoding`：選用。輸入以下其中之一：`utf8`、`hex`、`base64`、`base64url`。預設值為 `utf8`。
+ `Buffer.isBuffer(object)`

  檢查 `object` 是否為緩衝區。傳回 `true` 或 `false`。
  + `object`：輸入物件。
+ `Buffer.isEncoding(encoding)`

  檢查是否支援 `encoding`。傳回 `true` 或 `false`。
  + `encoding`：選用。輸入以下其中之一：`utf8`、`hex`、`base64`、`base64url`。預設值為 `utf8`。

此模組提供以下緩衝區原型方法：
+ `Buffer.prototype.compare(target[, targetStart[, targetEnd[, sourceStart[, sourceEnd]]]])`

  將 `Buffer` 與目標比較。如果兩者相同則傳回 `0`，如果 `buffer` 在前面則傳回 `1`，或如果 `target` 在前面則傳回 `-1`。
  + `target`：輸入 `Buffer`。
  + `targetStart`：選用。輸入整數。預設值為 0。
  + `targetEnd`：選用。輸入整數。預設值為 `target` 長度。
  + `sourceStart`：選用。輸入整數。預設值為 0。
  + `sourceEnd`：選用。輸入整數。預設值為 `Buffer` 長度。
+ `Buffer.prototype.copy(target[, targetStart[, sourceStart[, sourceEnd]]])`

  將緩衝區複製到 `target`。
  + `target`：輸入 `Buffer` 或 `Uint8Array`。
  + `targetStart`：選用。輸入整數。預設值為 0。
  + `sourceStart`：選用。輸入整數。預設值為 0。
  + `sourceEnd`：選用。輸入整數。預設值為 `Buffer` 長度。
+ `Buffer.prototype.equals(otherBuffer)`

  將 `Buffer` 與 `otherBuffer` 比較。傳回 `true` 或 `false`。
  + `otherBuffer`：輸入字串。
+ `Buffer.prototype.fill(value[, offset[, end][, encoding])`

  以 `value` 填入 `Buffer`。
  + `value`：輸入字串、`Buffer` 或整數。
  + `offset`：選用。輸入整數。
  + `end`：選用。輸入整數。
  + `encoding`：選用。輸入以下其中之一：`utf8`、`hex`、`base64`、`base64url`。預設值為 `utf8`。
+ `Buffer.prototype.includes(value[, byteOffset][, encoding])`

  搜尋 `Buffer` 中的 `value`。傳回 `true` 或 `false`。
  + `value`：輸入字串、`Buffer`、`Uint8Array`、或整數。
  + `byteOffset`：選用。輸入整數。
  + `encoding`：選用。輸入以下其中之一：`utf8`、`hex`、`base64`、`base64url`。預設值為 `utf8`。
+ `Buffer.prototype.indexOf(value[, byteOffset][, encoding])`

  首先搜尋 `Buffer` 中的第一個 `value`。如果找到了，則傳回 `index`；如果找不到，則傳回 `-1`。
  + `value`: 輸入字串、`Buffer`、Unit8Array 或 0 到 255 之間的整數。
  + `byteOffset`：選用。輸入整數。
  + `encoding`：選用。如果 `value` 是字串，請輸入以下其中一項：`utf8`、`hex`、`base64`、`base64url`。預設值為 `utf8`。
+ `Buffer.prototype.lastIndexOf(value[, byteOffset][, encoding])`

  搜尋 `Buffer` 中的最後一個 `value`。如果找到了，則傳回 `index`；如果找不到，則傳回 `-1`。
  + `value`: 輸入字串、`Buffer`、Unit8Array 或 0 到 255 之間的整數。
  + `byteOffset`：選用。輸入整數。
  + `encoding`：選用。如果 `value` 是字串，請輸入以下其中一項：`utf8`、`hex`、`base64`、`base64url`。預設值為 `utf8`。
+ `Buffer.prototype.readInt8(offset)`

  從 `Buffer` 的偏移值 `offset` 讀取 `Int8`。
  + `offset`：輸入整數。
+ `Buffer.prototype.readIntBE(offset, byteLength)`

  從 `Buffer` 的偏移值 `offset` 讀取大端序 `Int`。
  + `offset`：輸入整數。
  + `byteLength`：選用。輸入從 `1` 到 `6` 的整數。
+ `Buffer.prototype.readInt16BE(offset)`

  從 `Buffer` 的偏移值 `offset` 讀取大端序 `Int16`。
  + `offset`：輸入整數。
+ `Buffer.prototype.readInt32BE(offset)`

  從 `Buffer` 的偏移值 `offset` 讀取大端序 `Int32`。
  + `offset`：輸入整數。
+ `Buffer.prototype.readIntLE(offset, byteLength)`

  從 `Buffer` 的偏移值 `offset` 讀取小端序 `Int`。
  + `offset`：輸入整數。
  + `byteLength`：輸入從 `1` 到 `6` 的整數。
+ `Buffer.prototype.readInt16LE(offset)`

  從 `Buffer` 的偏移值 `offset` 讀取小端序 `Int16`。
  + `offset`：輸入整數。
+ `Buffer.prototype.readInt32LE(offset)`

  從 `Buffer` 的偏移值 `offset` 讀取小端序 `Int32`。
  + `offset`：輸入整數。
+ `Buffer.prototype.readUInt8(offset)`

  從 `Buffer` 的偏移值 `offset` 讀取 `UInt8`。
  + `offset`：輸入整數。
+ `Buffer.prototype.readUIntBE(offset, byteLength)`

  從 `Buffer` 的偏移值 `offset` 讀取大端序 `UInt`。
  + `offset`：輸入整數。
  + `byteLength`：輸入從 `1` 到 `6` 的整數。
+ `Buffer.prototype.readUInt16BE(offset)`

  從 `Buffer` 的偏移值 `offset` 讀取大端序 `UInt16`。
+ 
  + `offset`：輸入整數。
+ `Buffer.prototype.readUInt32BE(offset)`

  從 `Buffer` 的偏移值 `offset` 讀取大端序 `UInt32`。
  + `offset`：輸入整數。
+ `Buffer.prototype.readUIntLE(offset, byteLength)`

  從 `Buffer` 的偏移值 `offset` 讀取小端序 `UInt`。
  + `offset`：輸入整數。
  + `byteLength`：輸入從 `1` 到 `6` 的整數。
+ `Buffer.prototype.readUInt16LE(offset)`

  從 `Buffer` 的偏移值 `offset` 讀取小端序 `UInt16`。
  + `offset`：輸入整數。
+ `Buffer.prototype.readUInt32LE(offset)`

  從 `Buffer` 的偏移值 `offset` 讀取小端序 `UInt32`。
  + `offset`：輸入整數。
+ `Buffer.prototype.readDoubleBE([offset])`

  從 `Buffer` 的偏移值 `offset` 讀取 64 位元大端序雙精度浮點數。
  + `offset`：選用。輸入整數。
+ `Buffer.prototype.readDoubleLE([offset])`

  從 `Buffer` 的偏移值 `offset` 讀取 64 位元小端序雙精度浮點數。
  + `offset`：選用。輸入整數。
+ `Buffer.prototype.readFloatBE([offset])`

  從 `Buffer` 的偏移值 `offset` 讀取 32 位元大端序浮點數。
  + `offset`：選用。輸入整數。
+ `Buffer.prototype.readFloatLE([offset])`

  從 `Buffer` 的偏移值 `offset` 讀取 32 位元小端序浮點數。
  + `offset`：選用。輸入整數。
+ `Buffer.prototype.subarray([start[, end]])`

  傳回 `Buffer` 的副本，並使用新的 `start` 和 `end` 偏移和裁剪。
  + `start`：選用。輸入整數。預設值為 0。
  + `end`：選用。輸入整數。預設值為緩衝區長度。
+ `Buffer.prototype.swap16()`

  交換 `Buffer` 陣列的位元組順序，將其視為 16 位元數字的陣列。`Buffer` 的長度必須是 2 的倍數，否則您將收到錯誤訊息。
+ `Buffer.prototype.swap32()`

  交換 `Buffer` 陣列的位元組順序，將其視為 32 位元數字的陣列。`Buffer` 的長度必須是 4 的倍數，否則您將收到錯誤訊息。
+ `Buffer.prototype.swap64()`

  交換 `Buffer` 陣列的位元組順序，將其視為 64 位元數字的陣列。`Buffer` 的長度必須是 8 的倍數，否則您將收到錯誤訊息。
+ `Buffer.prototype.toJSON()`

  以 JSON 格式傳回 `Buffer`。
+ `Buffer.prototype.toString([encoding[, start[, end]]])`

  將 `Buffer` 從 `start` 到 `end` 轉換為編碼字串。
  + `encoding`：選用。輸入以下其中之一：`utf8`、`hex`、`base64` 或 `base64url`。預設值為 `utf8`。
  + `start`：選用。輸入整數。預設值為 0。
  + `end`：選用。輸入整數。預設值為緩衝區長度。
+ `Buffer.prototype.write(string[, offset[, length]][, encoding])`

  如果空間足夠，則將編碼 `string` 寫入 `Buffer`，如果空間不足，則寫入被截斷的 `string`。
  + `string`：輸入字串。
  + `offset`：選用。輸入整數。預設值為 0。
  + `length`：選用。輸入整數。預設值是字串的長度。
  + `encoding`：選用。選擇性地輸入以下其中一項：`utf8`、`hex`、`base64` 或 `base64url`。預設值為 `utf8`。
+ `Buffer.prototype.writeInt8(value, offset, byteLength)`

  將 `Int8` `value` (長度為 `byteLength`) 寫入 `Buffer` 的偏移值 `offset`。
  + `value`：輸入整數。
  + `offset`：輸入整數
  + `byteLength`：輸入從 `1` 到 `6` 的整數。
+ `Buffer.prototype.writeIntBE(value, offset, byteLength)`

  將 `value` 寫入 `Buffer` 的偏移值 `offset`，使用大端序。
  + `value`：輸入整數。
  + `offset`：輸入整數
  + `byteLength`：輸入從 `1` 到 `6` 的整數。
+ `Buffer.prototype.writeInt16BE(value, offset, byteLength)`

  將 `value` 寫入 `Buffer` 的偏移值 `offset`，使用大端序。
  + `value`：輸入整數。
  + `offset`：輸入整數
  + `byteLength`：輸入從 `1` 到 `6` 的整數。
+ `Buffer.prototype.writeInt32BE(value, offset, byteLength)`

  將 `value` 寫入 `Buffer` 的偏移值 `offset`，使用大端序。
  + `value`：輸入整數。
  + `offset`：輸入整數
  + `byteLength`：輸入從 `1` 到 `6` 的整數。
+ `Buffer.prototype.writeIntLE(offset, byteLength)`

  將 `value` 寫入 `Buffer` 的偏移值 `offset`，使用小端序。
  + `offset`：輸入整數。
  + `byteLength`：輸入從 `1` 到 `6` 的整數。
+ `Buffer.prototype.writeInt16LE(offset, byteLength)`

  將 `value` 寫入 `Buffer` 的偏移值 `offset`，使用小端序。
  + `offset`：輸入整數。
  + `byteLength`：輸入從 `1` 到 `6` 的整數。
+ `Buffer.prototype.writeInt32LE(offset, byteLength)`

  將 `value` 寫入 `Buffer` 的偏移值 `offset`，使用小端序。
  + `offset`：輸入整數。
  + `byteLength`：輸入從 `1` 到 `6` 的整數。
+ `Buffer.prototype.writeUInt8(value, offset, byteLength)`

  將 `UInt8` `value` (長度為 `byteLength`) 寫入 `Buffer` 的偏移值 `offset`。
  + `value`：輸入整數。
  + `offset`：輸入整數
  + `byteLength`：輸入從 `1` 到 `6` 的整數。
+ `Buffer.prototype.writeUIntBE(value, offset, byteLength)`

  將 `value` 寫入 `Buffer` 的偏移值 `offset`，使用大端序。
  + `value`：輸入整數。
  + `offset`：輸入整數
  + `byteLength`：輸入從 `1` 到 `6` 的整數。
+ `Buffer.prototype.writeUInt16BE(value, offset, byteLength)`

  將 `value` 寫入 `Buffer` 的偏移值 `offset`，使用大端序。
  + `value`：輸入整數。
  + `offset`：輸入整數
  + `byteLength`：輸入從 `1` 到 `6` 的整數。
+ `Buffer.prototype.writeUInt32BE(value, offset, byteLength)`

  將 `value` 寫入 `Buffer` 的偏移值 `offset`，使用大端序。
  + `value`：輸入整數。
  + `offset`：輸入整數
  + `byteLength`：輸入從 `1` 到 `6` 的整數。
+ `Buffer.prototype.writeUIntLE(value, offset, byteLength)`

  將 `value` 寫入 `Buffer` 的偏移值 `offset`，使用小端序。
  + `value`：輸入整數。
  + `offset`：輸入整數
  + `byteLength`：輸入從 `1` 到 `6` 的整數。
+ `Buffer.prototype.writeUInt16LE(value, offset, byteLength)`

  將 `value` 寫入 `Buffer` 的偏移值 `offset`，使用小端序。
  + `value`：輸入整數。
  + `offset`：輸入整數
  + `byteLength`：輸入從 `1` 到 `6` 的整數。
+ `Buffer.prototype.writeUInt32LE(value, offset, byteLength)`

  將 `value` 寫入 `Buffer` 的偏移值 `offset`，使用小端序。
  + `value`：輸入整數。
  + `offset`：輸入整數
  + `byteLength`：輸入從 `1` 到 `6` 的整數。
+ `Buffer.prototype.writeDoubleBE(value, [offset])`

  將 `value` 寫入 `Buffer` 的偏移值 `offset`，使用大端序。
  + `value`：輸入整數。
  + `offset`：選用。輸入整數。預設值為 0。
+ `Buffer.prototype.writeDoubleLE(value, [offset])`

  將 `value` 寫入 `Buffer` 的偏移值 `offset`，使用小端序。
  + `value`：輸入整數。
  + `offset`：選用。輸入整數。預設值為 0。
+ `Buffer.prototype.writeFloatBE(value, [offset])`

  將 `value` 寫入 `Buffer` 的偏移值 `offset`，使用大端序。
  + `value`：輸入整數。
  + `offset`：選用。輸入整數。預設值為 0。
+ `Buffer.prototype.writeFloatLE(value, [offset])`

  將 `value` 寫入 `Buffer` 的偏移值 `offset`，使用小端序。
  + `value`：輸入整數。
  + `offset`：選用。輸入整數。預設值為 0。

支援以下執行個體方法：
+ `buffer[index]`

  取得和設定 `Buffer` 中偏移值 `index` 的八位元組 (位元組)。
  + 取得從 `0` 到 `255` 的數字。或設定一個從 `0` 到 `255` 的數字。

支援以下執行個體屬性：
+ `buffer`

  取得緩衝區的 `ArrayBuffer` 物件。
+ `byteOffset`

  取得緩衝區 `Arraybuffer` 物件的 `byteOffset`。
+ `length`

  取得緩衝區位元組計數。

**注意**  
所有緩衝區模組方法都是 JavaScript 執行時間 2.0 的新功能。

### 查詢字串
<a name="writing-functions-javascript-features-builtin-modules-query-string-20"></a>

**注意**  
[CloudFront Functions 事件物件](functions-event-structure.md)會自動剖析 URL 查詢字串。這意味著在大多數情況下，您不需要使用此模組。

查詢字串模組 (`querystring`) 提供剖析和格式化 URL 查詢字串的方法。您可以使用 `require('querystring')` 加載模組。此模組提供下列方法。

`querystring.escape(string)`  
URL 編碼給定的 `string`，傳回逸出的查詢字串。該方法由 `querystring.stringify()` 使用，並且不應直接使用。

`querystring.parse(string[, separator[, equal[, options]]])`  
剖析查詢字串 (`string`) 並傳回物件。  
`separator` 參數是用來分隔查詢字串中的鍵/值對的子字串。其在預設情況下為 `&`。  
`equal` 參數是用來分隔查詢字串中的鍵和值的子字串。其在預設情況下為 `=`。  
`options` 參數是具有下列鍵的物件：    
`decodeURIComponent function`  
解碼查詢字串中百分比編碼字元的函數。其在預設情況下為 `querystring.unescape()`。  
`maxKeys number`  
要剖析的鍵的最大數量。其在預設情況下為 `1000`。使用 `0` 的值移除計數鍵的限制。
根據預設，查詢字串中的百分比編碼字元會假設為使用 UTF-8 編碼。無效的 UTF-8 序列會被取代為 `U+FFFD` 取代字元。  
例如，對於下列查詢字串：  

```
'name=value&abc=xyz&abc=123'
```
`querystring.parse()` 的返回值是：  

```
{
name: 'value',
abc: ['xyz', '123']
}
```
`querystring.decode()` 是 的別名。`querystring.parse()`

`querystring.stringify(object[, separator[, equal[, options]]])`  
序列化 `object` 並傳回查詢字串。  
`separator` 參數是用來分隔查詢字串中的鍵/值對的子字串。其在預設情況下為 `&`。  
`equal` 參數是用來分隔查詢字串中的鍵和值的子字串。其在預設情況下為 `=`。  
`options` 參數是具有下列鍵的物件：    
`encodeURIComponent function`  
用於將 URL 不安全字元轉換為查詢字串中的百分比編碼的函數。其在預設情況下為 `querystring.escape()`。
根據預設，在查詢字串中需要百分比編碼的字元會編碼為 UTF-8。若要使用不同的編碼，請指定 `encodeURIComponent` 選項。  
例如，對於以下程式碼：  

```
querystring.stringify({ name: 'value', abc: ['xyz', '123'], anotherName: '' });
```
返回值是：  

```
'name=value&abc=xyz&abc=123&anotherName='
```
`querystring.encode()` 是 `querystring.stringify()` 的別名。

`querystring.unescape(string)`  
解碼給定 `string` 中的 URL 百分比編碼字元，傳回未逸出的查詢字串。此方法由 `querystring.parse()` 使用，並且不應直接使用。

### 加密
<a name="writing-functions-javascript-features-builtin-modules-crypto-20"></a>

密碼編譯模組 (`crypto`) 提供標準雜湊和雜湊型訊息身分驗證碼 (HMAC) 協助程式。您可以使用 `require('crypto')` 加載模組。

**雜湊方法**

`crypto.createHash(algorithm)`  
建立並傳回雜湊物件，藉助此物件，您可以使用給定的演算法產生雜湊摘要：`md5`、`sha1` 或 `sha256`。

`hash.update(data)`  
使用給定的 `data` 更新雜湊內容。

`hash.digest([encoding])`  
計算使用 `hash.update()` 傳遞的所有資料的摘要。編碼可以是 `hex`、`base64` 或 `base64url`。

**HMAC 方法**

`crypto.createHmac(algorithm, secret key)`  
建立並返回使用給定 `algorithm` 和 `secret key` 的 HMAC 物件。演算法可以是 `md5`、`sha1` 或 `sha256`。

`hmac.update(data)`  
使用給定的 `data` 更新 HMAC 內容。

`hmac.digest([encoding])`  
計算使用 `hmac.update()` 傳遞的所有資料的摘要。編碼可以是 `hex`、`base64` 或 `base64url`。

## 限制功能
<a name="writing-functions-javascript-features-restricted-features-20"></a>

由於安全考量，下列 JavaScript 語言功能不受支援或受到限制。

**動態程式碼評估**  
不支援動態程式碼評估。如果嘗試此評估，`eval()` 和 `Function` 建構子都會丟出錯誤。例如，`const sum = new Function('a', 'b', 'return a + b')` 丟出錯誤。

**計時器**  
不支援 `setTimeout()`、`setImmediate()` 和 `clearTimeout()` 函數。在函數執行時期間未推遲或產生任何佈建。您的函數必須同步執行方可完成。

**日期和時間戳記**  
基於安全考量，無法存取高解析度計時器。查詢當前時間的所有 `Date` 方法始終在單個函數執行的生命週期內返回相同的值。返回的時間戳記是函數開始執行的時間。因此，您無法測量函數中的經過時間。

**檔案系統存取**  
沒有檔案系統存取權。例如，沒有類似 Node.js 中的檔案系統存取 `fs` 模組。

**處理存取**  
沒有處理存取。例如沒有 `process` 全域物件可像 Node.js 一樣處理資訊存取。

**環境變數**  
無法存取環境變數。您可以改為使用 CloudFront KeyValueStore 為您的 CloudFront Functions 建立鍵值對的集中式資料儲存。CloudFront KeyValueStore 可動態更新組態資料，不需要部署程式碼變更。如需詳細資訊，請參閱[Amazon CloudFront KeyValueStore](kvs-with-functions.md)。

**網路存取**  
不支援網路呼叫。例如，不支援 XHR、HTTP(S) 和通訊端。

# 鍵值存放區的協助程式方法
<a name="functions-custom-methods"></a>

**注意**  
CloudFront Functions 的鍵值存放區 helper 方法呼叫不會觸發 AWS CloudTrail 資料事件。這些事件不會記錄在 CloudTrail 事件歷史記錄中。如需詳細資訊，請參閱[使用 記錄 Amazon CloudFront API 呼叫 AWS CloudTrail](logging_using_cloudtrail.md)。

如果您使用 [CloudFront 鍵值存放區](kvs-with-functions.md)在您建立的函數中包含鍵值，則本節內容適用。CloudFront Functions 具有的模組可提供三種協助程式方法來讀取鍵值存放區中的值。

若要在函數程式碼中使用此模組，請確定您已[將索引鍵值存放區與函數建立關聯](kvs-with-functions-associate.md)。

接著，在函數程式碼的第一行中包含下列陳述式：

```
import cf from 'cloudfront';
const kvsHandle = cf.kvs();
```



## `get()` 方法
<a name="functions-custom-methods-get"></a>

使用此方法傳回您指定的鍵名稱的鍵值。

**請求**

```
get("key", options);
```
+ `key`：需要擷取其值的鍵名稱
+ `options`：有一個選項，`format`。它可以確保函數正確解析資料。可能的值如下：
  + `string`：(預設值) 以 UTF8 編碼
  + `json` 
  + `bytes`：原始二進位資料緩衝區

**請求範例**

```
const value = await kvsHandle.get("myFunctionKey", { format: "string"});
```

**回應**

回應是 `promise`，會以使用 `options` 請求的格式解析為值。根據預設，值會以字串傳回。

### 錯誤處理
<a name="error-handling-exists-method"></a>

當您請求的鍵不存在於關聯的鍵值存放區時，`get()` 方法會傳回錯誤。若要管理此使用案例，您可以將 `try` 和 `catch` 區塊新增至程式碼。

**警告**  
使用 promise 組合器 (例如 `Promise.all`、`Promise.any`) 和 promise 鏈接方法 (例如 `then` 和 `catch`) 可能需要高函數記憶體用量。如果您的函數超過[函數記憶體配額上限](cloudfront-limits.md#limits-functions)，則無法執行。為了避免此錯誤，建議您依序或在迴圈中使用 `await` 語法來請求多重值。  
**範例**  

```
var value1 = await kvs.get('key1');
var value2 = await kvs.get('key2');
```
目前，使用 promise 組合器取得多重值並不會改善效能，範例如下。  

```
var values = await Promise.all([kvs.get('key1'), kvs.get('key2'),]);
```

## `exists()` 方法
<a name="functions-custom-methods-exists"></a>

使用此方法來識別鍵是否存在於鍵值存放區中。

**請求**

```
exists("key");
```

**請求範例**

```
const exist = await kvsHandle.exists("myFunctionkey");
```

**回應**

回應是傳回布林值 (`true` 或 `false`) 的 `promise`。此值指定鍵是否存在於鍵值存放區中。

## `meta()` 方法
<a name="functions-custom-methods-meta"></a>

此方法會傳回有關鍵值存放區的中繼資料。

**請求**

```
meta();
```

**請求範例**

```
const meta = await kvsHandle.meta();
```

**回應**

回應是一個 `promise`，可解析為具有以下屬性的物件：
+ `creationDateTime`：鍵值存放區建立的日期和時間，以 ISO 8601 格式表示。
+ `lastUpdatedDateTime`：上次從來源同步的鍵值存放區的日期和時間，以 ISO 8601 格式表示。該值不包括到邊緣的傳播時間。
+ `keyCount`：上次從來源同步後 KVS 中的總鍵數。

**回應範例**

```
{keyCount:3,creationDateTime:2023-11-30T23:07:55.765Z,lastUpdatedDateTime:2023-12-15T03:57:52.411Z}
```

# 原始伺服器修改的 Helper 方法
<a name="helper-functions-origin-modification"></a>

如果您動態更新或變更 CloudFront Functions 程式碼內請求所使用的原始伺服器，則本節適用。您只能在*檢視器請求* CloudFront Functions 時更新原始伺服器。CloudFront Functions 有一個模組，提供 helper 方法來動態更新或變更原始伺服器。

若要使用此模組，請使用 JavaScript 執行時期 2.0 建立 CloudFront 函數，並在函數程式碼的第一行中包含下列陳述式：

```
import cf from 'cloudfront';
```

如需詳細資訊，請參閱[適用於 CloudFront Functions 的 JavaScript 執行時期 2.0 功能](functions-javascript-runtime-20.md)。

**注意**  
測試 API 和測試主控台頁面不會測試是否已發生原始伺服器修改。不過，測試可確保函數程式碼執行時不會發生錯誤。

## 在 CloudFront Functions 和 Lambda@Edge 之間進行選擇
<a name="origin-modification-considerations"></a>

您可以使用 CloudFront Functions 或 Lambda@Edge 來更新原始伺服器。

使用 CloudFront Functions 更新原始伺服器時，您可以使用*檢視器請求*事件觸發程序，這表示使用此函數時，每個請求都會執行此邏輯。使用 Lambda@Edge 時，原始伺服器更新功能位於*原始伺服器請求*事件觸發程序上，這表示此邏輯僅在快取遺漏時執行。

您的選擇主要取決於您的工作負載，以及分佈上 CloudFront Functions 和 Lambda@Edge 的任何現有用量。下列考量可協助您決定是否使用 CloudFront Functions 或 Lambda@Edge 來更新您的原始伺服器。

CloudFront Functions 在下列情況下最有用：
+ 當您的請求是動態的 (表示無法快取) 且一律會前往原始伺服器時。CloudFront Functions 可提供更好的效能並降低整體成本。
+ 當您已有現有的檢視器請求 CloudFront 函數會在每個請求上執行時，您可以將原始伺服器更新邏輯新增至現有的函數。

若要使用 CloudFront Functions 更新原始伺服器，請參閱下列主題中的 helper 方法。

Lambda@Edge 在下列情況下最有用：
+ 當您有高度可快取的內容時，Lambda@Edge 可能更具成本效益，因為它只會在快取遺漏時執行，而 CloudFront Functions 會在每次請求時執行。
+ 當您已有現有的原始伺服器請求 Lambda@Edge 函數時，您可以將原始伺服器更新邏輯新增至現有的函數。
+ 當您的原始伺服器更新邏輯需要從第三方資料來源擷取資料時，例如 Amazon DynamoDB 或 Amazon S3。

如需 Lambda@Edge 的詳細資訊，請參閱「[使用 Lambda@Edge 在邊緣自訂](lambda-at-the-edge.md)」。

## updateRequestOrigin() 方法
<a name="update-request-origin-helper-function"></a>

使用 `updateRequestOrigin()` 方法更新請求的原始伺服器設定。您可以使用此方法更新已在分佈中定義的原始伺服器現有的原始伺服器屬性，或定義請求的新原始伺服器。若要這樣做，請指定您要變更的屬性。

**重要**  
您在 `updateRequestOrigin()` 中未指定的任何設定都會繼承現有原始伺服器的組態中的*相同設定*。

`updateRequestOrigin()` 方法設定的原始伺服器可以是任何 HTTP 端點，而且不需要是 CloudFront 分佈中的現有原始伺服器。

**備註**  
如果您要更新屬於原始伺服器群組的原始伺服器，則只會更新原始伺服器群組的*主要原始伺服器*。次要原始伺服器保持不變。來自修改原始伺服器且符合容錯移轉準則的任何回應代碼都會觸發容錯移轉至次要原始伺服器。
如果您要變更原始伺服器類型並啟用 OAC，請確定 `originAccessControlConfig` 中的原始伺服器類型符合新的原始伺服器類型。
您無法使用 `updateRequestOrigin()` 方法更新 [VPC 原始伺服器](private-content-vpc-origins.md)。請求將會失敗。

**請求**

```
updateRequestOrigin({origin properties})
```

`origin properties` 可以包含以下：

**domainName (選用)**  
原始伺服器的網域名稱。如果未提供，則會改用來自指派原始伺服器的網域名稱。    
**對於自訂原始伺服器**  
指定 DNS 網域名稱，例如 `www.example.com`。網域名稱不能包含冒號 (`:`)，也不能是 IP 地址。網域名稱長度上限為 253 個字元。  
**對於 S3 原始伺服器**  
指定 Amazon S3 儲存貯體的 DNS 網域名稱，例如 `amzn-s3-demo-bucket.s3.eu-west-1.amazonaws.com`。名稱可以高達 128 個字元，而且必須全部小寫。

**hostHeader （選用，適用於non-S3 自訂原始伺服器）**  
向原始伺服器提出請求時要使用的主機標頭。如果未提供，則會使用 domainName 參數的值。如果未提供主機標頭或網域名稱參數，則會使用指派原始伺服器的網域名稱，如果轉送至原始伺服器 (FTO) 政策包含主機，則會使用來自傳入請求的主機標頭。主機標頭不能包含冒號 (`:`)，也不能是 IP 地址。主機標頭最多可達 253 個字元。

**originPath (選用)**  
目錄路徑位於需定位內容請求的原始伺服器中。路徑的開頭應為正斜線 (/)，但結尾不應為正斜線。例如，不應以 `example-path/` 結尾。如果未提供，則會使用指派原始伺服器的原始路徑。    
**對於自訂原始伺服器**  
此路徑應以 URL 編碼且最多 255 個字元。

**customHeaders (選用)**  
您可以透過指定的標頭名稱與每個自訂標頭的值對，於請求中包含自訂標頭。格式與事件結構中請求和回應標頭的格式不同。使用下列索引鍵/值對語法：  

```
{"key1": "value1", "key2": "value2", ...}
```
您無法新增已列入不允許的標頭，且具有相同名稱的標頭也無法出現在傳入的請求 `headers` 中。函數程式碼中的標頭名稱必須為小寫。當 CloudFront Functions 將事件物件轉換回 HTTP 請求時，標頭名稱中每個單字的第一個字母會大寫，且單字之間用連字符分隔。  
例如，如果函數程式碼新增名為 `example-header-name` 的標頭，CloudFront 會將其轉換為 HTTP 請求中的 `Example-Header-Name`。如需詳細資訊，請參閱[CloudFront 無法新增到原始伺服器請求的自訂標頭](add-origin-custom-headers.md#add-origin-custom-headers-denylist)及[對邊緣函數的限制](edge-functions-restrictions.md)。  
如果未提供，則會使用來自指派原始伺服器的任何自訂標頭。

**connectionAttempts (選用)**  
CloudFront 會嘗試連線至原始伺服器的次數。最小值為 1，最大值為 3。如果未提供，則會使用來自指派原始伺服器的連線嘗試。

**originShield (選用)**  
這會啟用或更新 CloudFront Origin Shield。使用 Origin Shield 有利於降低原始伺服器的負載。如需詳細資訊，請參閱[使用 Amazon CloudFront Origin Shield](origin-shield.md)。如果未提供，則會使用來自指派原始伺服器的 Origin Shield 設定。    
**enabled (必要)**  
啟用或停用 Origin Shield 的布林值表達式。接受值：`true` 或 `false`。  
**region (啟用時需要)**  
 AWS 區域 適用於 Origin Shield 的 。指定對原始伺服器延遲最低的 AWS 區域 。使用區域代碼，而非區域名稱。例如，使用 `us-east-2` 指定美國東部 (俄亥俄) 區域。  
啟用 CloudFront Origin Shield 時，您必須為其指定 AWS 區域 。如需可用 AWS 區域 的清單並協助您選擇最適合原始伺服器的區域，請參閱 [選擇 Origin Shield AWS 的區域](origin-shield.md#choose-origin-shield-region)。

**originAccessControlConfig (選用)**  
此原始伺服器的原始存取控制 (OAC) 唯一識別碼。這只會在原始伺服器支援 CloudFront OAC 時使用，例如 Amazon S3、Lambda 函數 URL、MediaStore 和 MediaPackage V2。如果未提供，則會使用來自指派原始伺服器的 OAC 設定。  
這不支援舊版原始存取身分 (OAI)。如需詳細資訊，請參閱[限制對 AWS 原始伺服器的存取](private-content-restricting-access-to-origin.md)。    
**enabled (必要)**  
啟用或停用 OAC 的布林值表達式。接受值：`true` 或 `false`。  
**signingBehavior (啟用時需要)**  
指定 CloudFront 會簽署哪些請求 (將身分驗證資訊新增至其中)。針對最常見的使用案例指定 `always`。如需詳細資訊，請參閱[原始存取控制的進階設定](private-content-restricting-access-to-s3.md#oac-advanced-settings-s3)。  
此欄位可以有下列其中一個值：  
+ `always` – CloudFront 會簽署所有原始伺服器請求，並覆寫來自檢視器請求的 `Authorization` 標頭 (如果存在)。
+ `never` – CloudFront 不簽署任何原始伺服器請求。此值會關閉原始伺服器的原始存取控制。
+ `no-override` – 如果檢視器請求不包含 `Authorization` 標頭，則 CloudFront 會簽署原始伺服器請求。如果檢視器請求包含 `Authorization` 標頭，則 CloudFront 不會簽署原始伺服器請求，而是傳遞來自檢視器請求的 `Authorization` 標頭。
**警告**  
如要從檢視器請求傳遞 `Authorization` 標題，您必須將標題新增至原始伺服器請求政策中，適用於使用與此原始存取控制相關聯之原始伺服器的所有快取行為。如需詳細資訊，請參閱[使用政策控制原始伺服器請求](controlling-origin-requests.md)。  
**signingProtocol (啟用時需要)**  
OAC 的簽署通訊協定，將決定 CloudFront 簽署 (驗證) 請求的方式。唯一有效的值為 `sigv4`。  
**originType (啟用時需要)**  
此 OAC 的原始伺服器類型。有效值包括 `s3`、`mediapackagev2`、`mediastore` 與 `lambda`。

**timeout (選用)**  
您可以指定 CloudFront 應嘗試等待原始伺服器回應或傳送資料的逾時時間。如果未提供，則會使用來自指派原始伺服器的逾時設定。  
除非另行指定，否則這些逾時支援自訂原始伺服器和 Amazon S3 原始伺服器。  
**readTimeout (選用)**  
`readTimeout` 適用於下列兩個值：  
+ 在將請求轉送到自訂原始伺服器之後，CloudFront 等待回應的時間 (以秒為單位)。
+ CloudFront 在收到來自原始伺服器的回應封包後，並在接收下一個封包前，等待的時間長短 (以秒為單位) 
最短的逾時時間是 1 秒，最長是 120 秒。如需詳細資訊，請參閱[回應逾時](DownloadDistValuesOrigin.md#DownloadDistValuesOriginResponseTimeout)。  
**responseCompletionTimeout (選用)**  
從 CloudFront 到原始伺服器的請求可以保持開啟並等待回應的時間 (以秒為單位)。如果此時未從原始伺服器收到完整回應，CloudFront 會結束連線。  
`responseCompletionTimeout` 值必須大於或等於 `readTimeout` 的值。如需詳細資訊，請參閱[回應完成逾時](DownloadDistValuesOrigin.md#response-completion-timeout)。  
**keepAliveTimeout (選用)**  
此逾時僅適用於自訂原始伺服器，不適用於 Amazon S3 原始伺服器。(S3 原始伺服器組態會忽略這些設定。)   
`keepAliveTimeout` 指定 CloudFront 在收到上次封包的回應後維持與原始伺服器的連線所需的時間長度。最短的逾時時間是 1 秒，最長是 120 秒。如需詳細資訊，請參閱[保持連線逾時 (僅限自訂與 VPC 原始伺服器)](DownloadDistValuesOrigin.md#DownloadDistValuesOriginKeepaliveTimeout)。  
**connectionTimeout (選用)**  
嘗試建立與原始伺服器的連線時，CloudFront 所等待的秒數。最短的逾時時間是 1 秒，最長是 10 秒。如需詳細資訊，請參閱[連線逾時。](DownloadDistValuesOrigin.md#origin-connection-timeout)。

**customOriginConfig (選用)**  
使用 `customOriginConfig` 指定*非* Amazon S3 儲存貯體之原始伺服器的連線設定。有一個例外：如果 S3 儲存貯體設定為靜態網站託管，您可以指定這些設定。(其他類型的 S3 儲存貯體組態會忽略這些設定。) 如果未提供 `customOriginConfig`，則會使用來自指派原始伺服器的設定。    
**port (必要)。**  
CloudFront 用來連線至來源的 HTTP 連接埠。指定來源接聽使用的 HTTP 連接埠。  
**protocol (必要)**  
指定 CloudFront 用來連線至來源的通訊協定 (HTTP 或 HTTPS)。有效值如下：  
+ `http` — CloudFront 一律使用 HTTP 來連線至原始伺服器
+ `https` — CloudFront 一律使用 HTTPS 來連線至原始伺服器  
**sslProtocols (必要)**  
指定 CloudFront 透過 HTTPS 連線至原始伺服器時所使用的最低 SSL/TLS 通訊協定的清單。有效值包括 `SSLv3`、`TLSv1`、`TLSv1.1` 與 `TLSv1.2`。如需詳細資訊，請參閱[最低來源 SSL 通訊協定](DownloadDistValuesOrigin.md#DownloadDistValuesOriginSSLProtocols)。  
**ipAddressType (選用)**  
指定 CloudFront 用來連線至原始伺服器的 IP 位址類型。有效值包括 `ipv4`、`ipv6` 與 `dualstack`。只有在同時變更 `domainName` 屬性時，才支援變更 `ipAddressType`。

**sni （選用，適用於non-S3 自訂原始伺服器）**  
伺服器名稱指示 (SNI) 是 Transport Layer Security (TLS) 通訊協定的延伸，其中用戶端會指出其嘗試在 TLS 交握程序開始時連線到哪個主機名稱。此值應與原始伺服器上 TLS 憑證上的通用名稱相符。否則，您的原始伺服器可能會擲回錯誤。  
如果未提供，則會使用 `hostHeader` 參數中的 值。如果未提供主機標頭，則會使用 `domainName` 參數的值。  
如果未提供主機標頭或網域名稱參數，則會使用指派原始伺服器的網域名稱，如果轉送至原始伺服器 (FTO) 政策包含主機，則會使用來自傳入請求的主機標頭。SNI 不能包含冒號 (`:`)，也不能是 IP 地址。SNI 最多可達 253 個字元。

**allowedCertificateNames （選用，適用於non-S3 自訂原始伺服器）**  
您可以包含 CloudFront 在 TLS 與您的原始伺服器交握期間，用來驗證原始伺服器 TLS 憑證之網域相符的有效憑證名稱清單。此欄位預期有一組有效的網域名稱，並且可以包含萬用字元網域，例如 `*.example.com`。  
您最多可以指定 20 個允許的憑證名稱。每個憑證名稱最多可有 64 個字元。

**Example – 更新至 Amazon S3 請求原始伺服器**  
下列範例會將檢視器請求的原始伺服器變更為 S3 儲存貯體、啟用 OAC，以及重設傳送至原始伺服器的自訂標頭。  

```
cf.updateRequestOrigin({
    "domainName" : "amzn-s3-demo-bucket-in-us-east-1.s3.us-east-1.amazonaws.com",
    "originAccessControlConfig": {
        "enabled": true,
        "signingBehavior": "always",
        "signingProtocol": "sigv4",
        "originType": "s3"
    },
    // Empty object resets any header configured on the assigned origin
    "customHeaders": {}
});
```

**Example – 更新 Application Load Balancer 請求原始伺服器**  
下列範例會將檢視器請求的原始伺服器變更為 Application Load Balancer 原始伺服器，並設定自訂標頭和逾時。  

```
cf.updateRequestOrigin({
    "domainName" : "example-1234567890.us-east-1.elb.amazonaws.com",
    "timeouts": {
        "readTimeout": 30,
        "connectionTimeout": 5
    },
    "customHeaders": {
        "x-stage": "production",
        "x-region": "us-east-1"
    }
});
```

**Example – 在啟用 Origin Shield 的情況下更新原始伺服器**  
在下列範例中，分佈中的原始伺服器已啟用 Origin Shield。函數程式碼只會更新用於原始伺服器的網域名稱，並省略所有其他選用參數。在此情況下，Origin Shield 仍會與修改後的原始網域名稱搭配使用，因為 Origin Shield 參數未更新。  

```
cf.updateRequestOrigin({
    "domainName" : "www.example.com"
});
```

**Example – 更新主機標頭、SNI 和允許的憑證名稱**  
對於大多數使用案例，您不需要對前往原始伺服器的請求使用此類型的修改。除非您了解變更這些值的影響，否則不應使用這些參數。
下列範例會在對原始伺服器的請求上變更網域名稱、主機標頭、SNI 和允許的憑證。  

```
cf.updateRequestOrigin({ 
    "domainName": "www.example.com", 
    "hostHeader": "test.example.com", 
    "sni": "test.example.net", 
    "allowedCertificateNames": ["*.example.com", "*.example.net"],
});
```

## selectRequestOriginById() 方法
<a name="select-request-origin-id-helper-function"></a>

使用 `selectRequestOriginById()` 來更新現有的原始伺服器，方法是選取已在分佈中設定的不同原始伺服器。此方法使用更新原始伺服器所定義的所有相同設定。

此方法僅接受已在執行函數時所用的相同分佈中定義的原始伺服器。原始伺服器由原始伺服器 ID 參考，這是您在設定原始伺服器時定義的原始伺服器名稱。

如果您的分佈中已設定 VPC 原始伺服器，您可以使用此方法將原始伺服器更新為 VPC 原始伺服器。如需詳細資訊，請參閱[使用 VPC 原始伺服器限制存取](private-content-vpc-origins.md)。

**備註**  
`selectRequestOriginById()` 函數無法選取已啟用交互 TLS （原始伺服器） 的原始伺服器。嘗試使用此函數選取已啟用交互 TLS （原始伺服器） 的原始伺服器會導致驗證錯誤。
如果您的使用案例需要使用交互 TLS （原始伺服器） 來選擇動態原始伺服器，請`updateRequestOrigin()`改用 ，確保所有目標原始伺服器都使用相同的用戶端憑證。

**請求**

```
cf.selectRequestOriginById(origin_id, {origin_overrides})
```

在先前的範例中， `origin_id` 是一個字串，指向執行 函數之 分佈中原始伺服器的原始伺服器名稱。`origin_overrides `參數可以包含下列項目：

**hostHeader （選用，適用於non-S3 自訂原始伺服器）**  
向原始伺服器提出請求時要使用的主機標頭。如果未提供，則會使用 `domainName` 參數中的 值。  
如果未提供主機標頭或網域名稱參數，則會使用指派原始伺服器的網域名稱，如果轉送至原始伺服器 (FTO) 政策包含主機，則會使用來自傳入請求的主機標頭。主機標頭不能包含冒號 (`:`)，也不能是 IP 地址。主機標頭最多可達 253 個字元。

**sni （選用，適用於non-S3 自訂原始伺服器）**  
伺服器名稱指示 (SNI) 是 Transport Layer Security (TLS) 通訊協定的延伸，其中用戶端會指出其嘗試在 TLS 交握程序開始時連線到哪個主機名稱。此值應與原始伺服器上 TLS 憑證上的通用名稱相符。否則，您的原始伺服器可能會擲回錯誤。  
如果未提供，則會使用 `hostHeader` 參數中的 值。如果未提供主機標頭，則會使用 `domainName` 參數的值。  
如果未提供主機標頭或網域名稱參數，則會使用指派原始伺服器的網域名稱，如果轉送至原始伺服器 (FTO) 政策包含主機，則會使用來自傳入請求的主機標頭。SNI 不能包含冒號 (`:`)，也不能是 IP 地址。SNI 最多可達 253 個字元。

**allowedCertificateNames （選用，適用於non-S3 自訂原始伺服器）**  
您可以包含 CloudFront 在 TLS 與您的原始伺服器交握期間，用來驗證原始伺服器 TLS 憑證之網域相符的有效憑證名稱清單。此欄位預期有一組有效的網域名稱，並且可以包含萬用字元網域，例如 `*.example.com`。  
您最多可以指定 20 個允許的憑證名稱。每個憑證名稱最多可有 64 個字元。

**請求**

```
selectRequestOriginById(origin_id)
```

在上述範例中，`origin_id` 是指向執行函數之分佈中原始伺服器的原始伺服器名稱的字串。

**Example – 選取 Amazon S3 請求原始伺服器**  
下列範例會從與分佈相關聯的原始伺服器清單中選擇名為 `amzn-s3-demo-bucket-in-us-east-1` 的原始伺服器，並將 `amzn-s3-demo-bucket-in-us-east-1` 原始伺服器的組態設定套用至請求。  

```
cf.selectRequestOriginById("amzn-s3-demo-bucket-in-us-east-1");
```

**Example – 選取 Application Load Balancer 請求原始伺服器**  
下列範例會從與分佈相關聯的原始伺服器清單中選擇名為 `myALB-prod` 的 Application Load Balancer 原始伺服器，並將 `myALB-prod` 的組態設定套用至請求。  

```
cf.selectRequestOriginById("myALB-prod");
```

**Example – 選取 Application Load Balancer 請求原始伺服器並覆寫主機標頭**  
如同上述範例，下列範例`myALB-prod`會從與分佈相關聯的原始伺服器清單中選擇名為 的 Application Load Balancer 原始伺服器，並將 的組態設定套用至`myALB-prod`請求。不過，此範例會使用 覆寫主機標頭值`origin_overrides`。  

```
cf.overrideRequestOrigin("myALB-prod",{ 
        "hostHeader" : "test.example.com"
});
```

## createRequestOriginGroup() 方法
<a name="create-request-origin-group-helper-function"></a>

使用 `createRequestOriginGroup()` 定義兩個原始伺服器，以在需要高可用性的情況下用作容錯移轉的[原始伺服器群組](high_availability_origin_failover.md#concept_origin_groups.creating)。

原始伺服器群組包括兩個原始伺服器 (主要原始伺服器和次要原始伺服器)，以及您指定的容錯移轉準則。您建立原始伺服器群組以支援 CloudFront 中的原始伺服器容錯移轉。當您使用此方法建立或更新原始伺服器群組時，您可以指定原始伺服器群組，而不是單一原始伺服器。CloudFront 將使用容錯移轉準則，從主要原始伺服器容錯移轉至次要原始伺服器。

如果您的分佈中已設定 VPC 原始伺服器，您可以使用此方法來使用 VPC 原始伺服器建立原始伺服器群組。如需詳細資訊，請參閱[使用 VPC 原始伺服器限制存取](private-content-vpc-origins.md)。

**備註**  
`createRequestOriginGroup()` 函數不支援建立包含啟用互斥 TLS （原始伺服器） 的原始伺服器群組。無法透過 CloudFront Functions 動態建立具有互斥 TLS （原始） 原始伺服器的原始伺服器群組。
如果您需要具有相互 TLS （原始伺服器） 的原始伺服器容錯移轉功能，請直接在 CloudFront 分佈設定中設定原始伺服器群組，而不是在函數中動態建立原始伺服器群組。

### 請求
<a name="create-origin-group-request"></a>

```
createRequestOriginGroup({origin_group_properties})
```

在前面的範例中，`origin_group_properties` 包含以下：

**originIds (必要)**  
`origin_ids` 陣列，其中 `origin_id` 是指向執行函數之分佈中原始伺服器的原始伺服器名稱的字串。您必須提供兩個原始伺服器做為陣列的一部分。清單中的第一個原始伺服器是主要原始伺服器，第二個則做為容錯移轉用途的次要原始伺服器。

**originOverrides （選用）**  
 使用 `{origin_overrides}` 參數可覆寫一些進階設定。`origin overrides` 可以包含以下：    
**hostHeader （選用，適用於non-S3 自訂原始伺服器）**  
向原始伺服器提出請求時要使用的主機標頭。如果未提供，則會使用 `domainName` 參數中的 值。  
如果未提供主機標頭或網域名稱參數，則會使用指派原始伺服器的網域名稱，如果轉送至原始伺服器 (FTO) 政策包含主機，則會使用來自傳入請求的主機標頭。主機標頭不能包含冒號 (`:`)，也不能是 IP 地址。主機標頭最多可達 253 個字元。  
**sni （選用，適用於non-S3 自訂原始伺服器）**  
伺服器名稱指示 (SNI) 是 Transport Layer Security (TLS) 通訊協定的延伸，用戶端會在 TLS 交握程序開始時，指出其嘗試連線到哪個主機名稱。此值應與原始伺服器上 TLS 憑證上的通用名稱相符，否則原始伺服器可能會擲回錯誤。  
如果未提供，則會使用 `hostHeader` 參數中的 值。如果未提供主機標頭，則會使用 `domainName` 參數的值。  
如果未提供主機標頭或網域名稱參數，則會使用指派原始伺服器的網域名稱，如果轉送至原始伺服器 (FTO) 政策包含主機，則會使用來自傳入請求的主機標頭。SNI 不能包含冒號 (`:`)，也不能是 IP 地址。SNI 最多可達 253 個字元。  
**allowedCertificateNames （選用，適用於non-S3 自訂原始伺服器）**  
您可以包含 CloudFront 在 TLS 與您的原始伺服器交握期間，用來驗證原始伺服器 TLS 憑證之網域相符的有效憑證名稱清單。此欄位預期有一組有效的網域名稱，並且可以包含萬用字元網域，例如 `*.example.com`。  
您最多可以指定 20 個允許的憑證名稱。每個憑證名稱最多可有 64 個字元。

**selectionCriteria (選用)**  
選取要使用 `default` 原始伺服器容錯移轉準則或使用 `media-quality-score` 型容錯移轉邏輯。有效值如下：  
+ `default` 根據 `failoverCriteria` 中指定的狀態碼使用容錯移轉準則。如果您未在函數中設定 `selectionCriteria`，則會使用 `default`。
+ 使用媒體感知路由功能時，會使用 `media-quality-score`。

**failoverCriteria (必要)**  
從主要原始伺服器傳回的狀態碼陣列，將觸發 CloudFront 容錯移轉至次要原始伺服器。如果您覆寫現有的原始伺服器群組，此陣列會覆寫原始伺服器群組原始組態中設定的所有容錯移轉狀態碼。  
當您使用 `media-quality-score` `selectionCriteria` 時，CloudFront 會根據媒體品質分數嘗試路由請求。如果選取的原始伺服器傳回此陣列中設定的錯誤碼，CloudFront 會容錯移轉至另一個原始伺服器。

**Example – 建立請求原始伺服器群組**  
下列範例會使用原始伺服器 ID 為請求建立原始伺服器群組。這些原始伺服器 ID 來自用於執行此函數之分佈的原始伺服器群組組態。  
或者，您可以使用 `originOverrides` 覆寫 `sni`、 `hostHeader`和 的原始伺服器群組組態`allowedCertificateNames`。  

```
import cf from 'cloudfront';

function handler(event) {
    cf.createRequestOriginGroup({
        "originIds": [
            {
                "originId": "origin-1",
                "originOverrides": {
                    "hostHeader": "hostHeader.example.com",
                    "sni": "sni.example.com",
                    "allowedCertificateNames": ["cert1.example.com", "cert2.example.com", "cert3.example.com"]
                }
            },
            {
                "originId": "origin-2",
                "originOverrides": {
                    "hostHeader": "hostHeader2.example.com",
                    "sni": "sni2.example.com",
                    "allowedCertificateNames": ["cert4.example.com", "cert5.example.com"]
                }
            }
        ],
        "failoverCriteria": {
            "statusCodes": [500]
        }
    });
    
    event.request.headers['x-hookx'] = { value: 'origin-overrides' };
    return event.request;
}
```

# CloudFront SaaS Manager 屬性的 helper 方法
<a name="saas-specific-logic-function-code"></a>

使用 CloudFront SaaS Manager 的下列 helper 函數，在您建立的函數中擷取多租用戶分佈的值。若要在此頁面上使用範例，您必須先使用 JavaScript 執行時期 2.0 建立 CloudFront 函數。如需詳細資訊，[適用於 CloudFront Functions 的 JavaScript 執行時期 2.0 功能](functions-javascript-runtime-20.md)。

**Topics**
+ [

## 連線群組
](#connection-groups-helper-function)
+ [

## 分佈租用戶
](#distribution-tenants-helper-functions)

## 連線群組
<a name="connection-groups-helper-function"></a>

與分佈租用戶相關聯的連線群組具有網域名稱。

若要取得此值，請使用事件物件 `context` 子物件的 `endpoint` 欄位。

**請求**

```
const value = event.context.endpoint;
```

**回應**

回應是包含連線群組網域名稱的 `string`，例如 d111111abcdef8.cloudfront.net。只有當您的函數被調用具有相關聯連線群組的多租用戶分佈時，`endpoint` 欄位才會出現。如需詳細資訊，請參閱[內容物件](functions-event-structure.md#functions-event-structure-context)。

## 分佈租用戶
<a name="distribution-tenants-helper-functions"></a>

CloudFront Functions 有一個模組，可讓您存取特定的分佈租用戶值。

若要使用此模組，請在函數程式碼的第一行中包含下列陳述式：

```
import cf from 'cloudfront';
```

您只能在 `handler` 函數中直接或透過任何巢狀呼叫函數使用下列範例。

### `distributionTenant.id` 欄位
<a name="distribution-tenants-field"></a>

使用此欄位來取得分佈租用戶 ID 的值。

**請求**

```
const value = cf.distributionTenant.id;
```

**回應**

回應是包含分佈租用戶 ID 的 `string`，例如 `dt_1a2b3c4d5e6f7`。

**錯誤處理**

如果您的函數是針對標準分佈調用，則指定 `distributionTenant.id` 欄位將傳回 `distributionTenant module is not available` 類型錯誤。若要處理此使用案例，您可以將 `try` 和 `catch` 區塊新增至程式碼。

### `distributionTenant.parameters.get()` 方法
<a name="distribution-tenant-parameters-get-method"></a>

使用此方法可傳回您指定之分佈租用戶參數名稱的值。

```
distributionTenant.parameters.get("key");
```

`key`：您要為其擷取值的分佈租用戶參數名稱。

**請求 **

```
const value = distributionTenant.parameters.get("key");
```

**回應**

回應是 `string`，其中包含分佈租用戶參數的值。例如，如果您的鍵名稱為 `TenantPath`，則此參數的值可能是 `tenant1`。

**錯誤處理**

您可能會收到下列錯誤：
+ 如果您的函數是針對標準分佈調用，則 `distributionTenant.parameters.get()` 方法將傳回 `distributionTenant module is not available` 類型錯誤。
+ 當您指定的分佈租用戶參數不存在時，會傳回 `DistributionTenantParameterKeyNotFound` 錯誤。

若要管理這些使用案例，您可以將 `try` 和 `catch` 區塊新增至程式碼。

# 使用 async 和 await
<a name="async-await-syntax"></a>

CloudFront Functions JavaScript 執行時期函數 2.0 提供處理 `Promise` 物件的 `async` 和 `await` 語法。Promises 代表可以透過函數中標記為 `async` 的關鍵字 `await` 存取延遲結果。各種新的 WebCrypto 函數使用 Promises。

如需 `Promise` 物件的詳細資訊，請參閱 [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)。

**注意**  
您必須針對下列程式碼範例使用 JavaScript 執行時期 2.0。  
`await` 只能在 `async` 函數內使用，不支援 `async` 引數和關閉。

```
async function answer() {
    return 42;
}

// Note: async, await can be used only inside an async function. async arguments and closures are not supported.

async function handler(event) {
    // var answer_value = answer(); // returns Promise, not a 42 value
    let answer_value = await answer(); // resolves Promise, 42
    console.log("Answer"+answer_value);
    event.request.headers['answer'] = { value : ""+answer_value };
    return event.request;
}
```

下面的範例 JavaScript 程式碼顯示如何使用 `then` 鏈接方法查看 Promises。您可以使用 `catch` 來檢視錯誤。

**警告**  
使用 promise 組合器 (例如 `Promise.all`、`Promise.any`) 和 promise 鏈接方法 (例如 `then` 和 `catch`) 可能需要高函數記憶體用量。如果您的函數超過[函數記憶體配額上限](cloudfront-limits.md#limits-functions)，則無法執行。為了避免此錯誤，建議您使用 `await` 語法，而非 `promise` 方法。

```
async function answer() {
    return 42;
}

async function squared_answer() {
   return answer().then(value => value * value)
} 
// Note: async, await can be used only inside an async function. async arguments and closures are not supported.
async function handler(event) {
    // var answer_value = answer(); // returns Promise, not a 42 value
    let answer_value = await squared_answer(); // resolves Promise, 42
    console.log("Answer"+answer_value);
    event.request.headers['answer'] = { value : ""+answer_value };
    return event.request;
}
```

# CloudFront Functions 的 CWT 支援
<a name="cwt-support-cloudfront-functions"></a>

本節提供 CloudFront Functions 中 CBOR Web Token (CWT) 支援的詳細資訊，可在 CloudFront Edge Locations 啟用安全字符型身分驗證和授權。此支援是以模組形式提供，可在 CloudFront Function 中存取。

若要使用此模組，請使用 JavaScript 執行期 2.0 建立 CloudFront 函數，並在函數程式碼的第一行中包含下列陳述式：

```
import cf from 'cloudfront';
```

與此模組相關聯的方法可透過 存取 （其中 \$1 是萬用字元，代表模組中存在的不同函數）：

```
cf.cwt.*
```

如需詳細資訊，請參閱[適用於 CloudFront Functions 的 JavaScript 執行時期 2.0 功能](functions-javascript-runtime-20.md)。

目前，模組僅支援具有 HS256 (HMAC-SHA256) 演算法的 MAC0 結構，字符大小上限為 1KB。

## 字符結構
<a name="token-structure"></a>

本節涵蓋 CWT 模組預期的字符結構。模組預期字符會正確標記和識別 （例如 COSE MAC0)。此外，對於字符的結構，模組遵循 [CBOR 物件簽署和加密 (COSE) 【RFC 8152】](https://datatracker.ietf.org/doc/html/rfc8152) 設定的標準。

```
( // CWT Tag (Tag value: 61) --- optional    
    ( // COSE MAC0 Structure Tag (Tag value: 17) --- required        
        [            
            protectedHeaders,            
            unprotectedHeaders,            
            payload,            
            tag,        
        ]    
    )
)
```

**Example ：使用 COSE MAC0 結構的 CWT**  

```
61( // CWT tag     
    17( // COSE_MAC0 tag       
        [         
            { // Protected Headers           
                1: 4  // algorithm : HMAC-256-64         
            },         
            { // Unprotected Headers           
                4: h'53796d6d6574726963323536' // kid : Symmetric key id          
            },         
            { // Payload           
                1: "https://iss.example.com", // iss           
                2: "exampleUser", // sub           
                3: "https://aud.example.com", // aud           
                4: 1444064944, // exp           
                5: 1443944944, // nbf           
                6: 1443944944, // iat         
            },         
            h'093101ef6d789200' // tag       
        ]     
    )   
)
```
產生字符時，CWT 標籤是選用的。不過，需要 COSE 結構標籤。

## validateToken() 方法
<a name="validatetoken-method"></a>

函數會使用指定的金鑰解碼和驗證 CWT 字符。如果驗證成功，則會傳回解碼的 CWT 字符。否則，它會擲回錯誤。請注意，此函數不會對宣告集進行驗證。

### 請求
<a name="validatetoken-request"></a>

```
cf.cwt.validateToken(token, handlerContext{key})
```Parameters

**字符 （必要）**  
用於驗證的編碼字符。這必須是 JavaScript 緩衝區。

**handlerContext （必要）**  
存放 validateToken 呼叫內容的 JavaScript 物件。目前僅支援 金鑰屬性。

**金鑰 （必要）**  
訊息摘要運算的私密金鑰。可做為字串或 JavaScript 緩衝區提供。

### 回應
<a name="validatetoken-response"></a>

當 `validateToken()`方法傳回成功驗證的字符時，函數的回應會以下列格式`CWTObject`顯示 。解碼後，所有宣告金鑰都會以字串表示。

```
CWTObject {    
    protectedHeaders,    
    unprotectedHeaders,    
    payload
}
```

### 範例 - 使用作為字符一部分傳送的 kid 驗證字符
<a name="validatetoken-example"></a>

此範例示範 CWT 字符驗證，其中會從 標頭擷取 kid。接著 kid 會傳遞至 CloudFront Functions KeyValueStore，以擷取用於驗證權杖的私密金鑰。

```
import cf from 'cloudfront'

const CwtClaims = {
   iss: 1,
   aud: 3,
   exp: 4
}

async function handler(event) {
    try {
        let request = event.request;
        let encodedToken = request.headers['x-cwt-token'].value;
        let kid = request.headers['x-cwt-kid'].value;
                
        // Retrieve the secret key from the kvs
        let secretKey = await cf.kvs().get(kid);
                 
        // Now you can use the secretKey to decode & validate the token.
        let tokenBuffer = Buffer.from(encodedToken, 'base64url');
                
        let handlerContext = {
           key: secretKey,
        }
                
        try {
            let cwtObj = cf.cwt.validateToken(tokenBuffer, handlerContext);
                        
            // Check if token is expired
            const currentTime = Math.floor(Date.now() / 1000); // Current time in seconds
            if (cwtObj[CwtClaims.exp] && cwtObj[CwtClaims.exp] < currentTime) {
                return {
                    statusCode: 401,
                    statusDescription: 'Token expired'
                };
            }
        } catch (error) {
            return {
               statusCode: 401,
               statusDescription: 'Invalid token'
            };
         }
    } catch (error) {
        return {
            statusCode: 402,
            statusDescription: 'Token processing failed'
        };
     }
    return request;
}
```

## generateToken() 方法
<a name="generatetoken-method"></a>

此函數會使用提供的承載和內容設定產生新的 CWT 字符。

### 請求
<a name="generatetoken-request"></a>

```
cf.cwt.generateToken(generatorContext, payload)
```Parameters

**generatorContext （必要）**  
這是 JavaScript 物件，可做為產生字符的內容，並包含下列索引鍵值對：    
**cwtTag （選用）**  
此值是布林值，如果 `true`指定`cwtTag`應新增 。  
**coseTag （必要）**  
指定 COSE 標籤類型。目前僅支援 `MAC0`。  
**金鑰 （必要）**  
用於運算訊息摘要的私密金鑰。此值可以是字串或 JavaScript `Buffer`。

**承載 （必要）**  
用於編碼的字符承載。承載必須是 `CWTObject` 格式。

### 回應
<a name="generatetoken-response"></a>

傳回包含編碼字符的 JavaScript 緩衝區。

**Example ：產生 CWT 字符**  

```
import cf from 'cloudfront';

const CwtClaims = {
    iss: 1,
    sub: 2,
    exp: 4
};

const CatClaims = {
    catu: 401,
    catnip: 402,
    catm: 403,
    catr: 404
};

const Catu = {
    host: 1,
    path: 2,
    ext: 3
};

const CatuMatchTypes = {
    prefix_match: 1,
    suffix_match: 2,
    exact_match: 3
};

const Catr = {
    renewal_method: 1,
    next_renewal_time: 2,
    max_uses: 3
};

async function handler(event) {
    try {
        const response = {
            statusCode: 200,
            statusDescription: 'OK',
            headers: {}
        };
        
        const commonAccessToken = {
            protected: {
                1: "5",
            },
            unprotected: {},
            payload: {
                [CwtClaims.iss]: "cloudfront-documentation",
                [CwtClaims.sub]: "cwt-support-on-cloudfront-functions",
                [CwtClaims.exp]: 1740000000,
                [CatClaims.catu]: {
                    [Catu.host]: {
                        [CatuMatchTypes.suffix_match]: ".cloudfront.net"
                    },
                    [Catu.path]: {
                        [CatuMatchTypes.prefix_match]: "/media/live-stream/cf-4k/"
                    },
                    [Catu.ext]: {
                        [CatuMatchTypes.exact_match]: [
                            ".m3u8",
                            ".ts",
                            ".mpd"
                        ]
                    }
                },
                [CatClaims.catnip]: [
                    "[IP_ADDRESS]",
                    "[IP_ADDRESS]"
                ],
                [CatClaims.catm]: [
                    "GET",
                    "HEAD"
                ],
                [CatClaims.catr]: {
                    [Catr.renewal_method]: "header_renewal",
                    [Catr.next_renewal_time]: 1750000000,
                    [Catr.max_uses]: 5
                }
            }
        };
        
        if (!request.headers['x-cwt-kid']) {
            throw new Error('Missing x-cwt-kid header');
        }
        
        const kid = request.headers['x-cwt-kid'].value;
        const secretKey = await cf.kvs().get(kid);
        
        if (!secretKey) {
            throw new Error('Secret key not found for provided kid');
        }
        
        try {
            const genContext = {
                cwtTag: true,
                coseTag: "MAC0",
                key: secretKey
            };
            
            const tokenBuffer = cf.cwt.generateToken(commonAccessToken, genContext);
            response.headers['x-generated-cwt-token'] = { value: tokenBuffer.toString('base64url') };
                        
            return response;
        } catch (tokenError) {
            return {
                statusCode: 401,
                statusDescription: 'Could not generate the token'
            };
        }
    } catch (error) {
        return {
            statusCode: 402,
            statusDescription: 'Token processing failed'
        };
    }
}
```

**Example ：根據某些邏輯重新整理權杖**  

```
import cf from 'cloudfront'

const CwtClaims = {
   iss: 1,
   aud: 3,
   exp: 4
}

async function handler(event) {
    try {
        let request = event.request;
        let encodedToken = request.headers['x-cwt-token'].value;
        let kid = request.headers['x-cwt-kid'].value;
        let secretKey = await cf.kvs().get(kid); // Retrieve the secret key from the kvs
                
        // Now you can use the secretKey to decode & validate the token.
        let tokenBuffer = Buffer.from(encodedToken, 'base64url');
                
        let handlerContext = {
           key: secretKey,
        }
                
        try {
            let cwtJSON = cf.cwt.validateToken(tokenBuffer, handlerContext);
                        
            // Check if token is expired
            const currentTime = Math.floor(Date.now() / 1000); // Current time in seconds
            if (cwtJSON[CwtClaims.exp] && cwtJSON[CwtClaims.exp] < currentTime) {
                // We can regnerate the token and add 8 hours to the expiry time
                cwtJSON[CwtClaims.exp] = Math.floor(Date.now() / 1000) + (8 * 60 * 60);
                                
                let genContext = {
                  coseTag: "MAC0",
                  key: secretKey
                }
                                
                let newTokenBuffer = cf.cwt.generateToken(cwtJSON, genContext);
                 request.headers['x-cwt-regenerated-token'] = newTokenBuffer.toString('base64url');
            }
        } catch (error) {
            return {
               statusCode: 401,
               statusDescription: 'Invalid token'
            };
         }
    }
    catch (error) {
        return {
            statusCode: 402,
            statusDescription: 'Token processing failed'
        };
     }
    return request;
}
```

# 一般協助程式方法
<a name="general-helper-methods"></a>

此頁面提供 CloudFront Functions 內的其他協助程式方法。若要使用這些方法，請使用 JavaScript 執行期 2.0 建立 CloudFront 函數。

```
import cf from 'cloudfront';
```

如需詳細資訊，請參閱[適用於 CloudFront Functions 的 JavaScript 執行時期 2.0 功能](functions-javascript-runtime-20.md)。

## `edgeLocation` 中繼資料
<a name="edge-location-metadata"></a>

此方法需要使用 `cloudfront`模組。

**注意**  
您只能將此方法用於檢視器請求函數。對於檢視器-回應函數，此方法為空。

使用此 JavaScript 物件來取得節點機場代碼、預期的[區域節點快取](HowCloudFrontWorks.md#CloudFrontRegionaledgecaches)區域或用於處理請求的 CloudFront 伺服器 IP 地址。此中繼資料僅適用於檢視器請求事件觸發。

```
cf.edgeLocation = {
    name: SEA
    serverIp: 1.2.3.4
    region: us-west-2
}
```

`cf.edgeLocation` 物件可以包含下列項目：

**name**  
處理請求之節點的三個字母 [IATA 代碼](https://en.wikipedia.org/wiki/IATA_airport_code)。

**serverIp**  
處理請求之伺服器的 IPv4 或 IPv6 地址。

**region**  
如果發生快取遺漏，*預期*請求使用的 CloudFront Regional Edge Cache (REC)。如果預期的 REC 無法使用，且請求使用備份 REC，則不會更新此值。這不包括正在使用的 Origin Shield 位置，除非主要 REC 和 Origin Shield 是相同的位置。

**注意**  
當 CloudFront 設定為使用原始伺服器容錯移轉時，不會再次叫用 CloudFront Functions。如需詳細資訊，請參閱[透過 CloudFront 原始伺服器容錯移轉最佳化高可用性](high_availability_origin_failover.md)。

## `rawQueryString()` 方法
<a name="raw-query-string-method"></a>

此方法不需要 `cloudFront`模組。

使用 `rawQueryString()`方法將未剖析和未變更的查詢字串擷取為字串。

**請求**

```
function handler(event) {
    var request = event.request;
    const qs = request.rawQueryString();
}
```

**回應**

將傳入請求的完整查詢字串傳回為字串值，而不含前置 `?`。
+ 如果沒有查詢字串，但 `?` 存在，則函數會傳回空字串。
+ 如果沒有查詢字串且 `?` 不存在，則函數會傳回 `undefined`。

**案例 1：傳回完整查詢字串 （沒有前置 `?`)**  
傳入請求 URL： `https://example.com/page?name=John&age=25&city=Boston`  
`rawQueryString()` 傳回： `"name=John&age=25&city=Boston"`

**案例 2：傳回空字串 （當 `?` 存在但沒有參數時）**  
傳入請求 URL： `https://example.com/page?`  
`rawQueryString()` 傳回： `""`

**案例 3：`undefined`傳回 （沒有查詢字串，也沒有 `?`)**  
傳入請求 URL： `https://example.com/page`  
`rawQueryString()` 傳回： `undefined`