具有Edge函式的HTTP要求篩選器

IMPORTANT
AEM Edge功能目前仍在測試階段。 功能和檔案可能會變更。 如需意見回饋,請連絡aemcs-edgecompute-feedback@adobe.com

瞭解如何使用AEM Edge函式實作HTTP請求篩選,以重寫或重新導向請求,或修改HTTP回應。

何時透過Edge函式篩選HTTP請求

AEM Edge函式可作為反向Proxy,在請求和回應抵達來源或使用者端之前對其執行進階處理。

這兩種情況包括:

在請求到達來源之前調整請求

在前往來源的途中攔截流量以:

  • 重寫要求來源、路徑或查詢。 將請求路由到不同的後端、路徑或查詢字串,讓來源接收正確的資源。
  • 重寫要求標頭。 在請求到達來源之前新增、移除或修改標頭。 例如,新增來源期望的地理或存取標題、移除來源忽略的標題,或變更標題值以改變請求行為。

在回應到達使用者端之前修改回應

在回訪使用者端(訪客)的途中攔截流量,以:

  • 變更回應HTML。 在頁面到達瀏覽器之前,在頁首和頁尾中插入JavaScript、個人化內容、重寫連結或拼接。
  • 在邊緣重新導向。 提供從CDN進行的大量舊版到新版URL重新導向,尤其是當重新導向規則需要程式設計邏輯時。
  • 依要求內容個人化。 依地理位置、裝置或公開訪客的對象而改變頁面或頁面區段。 這適用於發佈您網站網域上的流量,不適用於作者流量。

實作HTTP要求篩選

HTTP請求篩選使用兩個檔案。 config/cdn.yaml檔案會決定要攔截哪些流量並路由至您的AEM Edge函式。 src/index.js檔案執行要求或回應調整。

原始選取器與函式名稱必須對齊。 如果edgeFunctions.yaml宣告my-edge-function,則來源選擇器會在cdn.yaml中使用edgefunction-my-edge-function

設定CDN篩選器

# config/cdn.yaml (origin selector excerpt)
kind: "CDN"
version: "1"
data:
  originSelectors:
    rules:
      - name: route-to-edge-function
        when:
          allOf:
            - { reqProperty: tier, equals: "publish" } # publish traffic only; skip author
            - { reqProperty: domain, equals: "www.example.com" } # your site hostname
            - { reqProperty: originalPath, matches: "(/[^./]+|\\.html|/)$" } # page URLs; skip static assets (.css, .js, images, fonts)
            # - { reqProperty: method, in: ["GET", "HEAD"] } # optional: navigation only; skip POST, PUT, and other methods with bodies
            - { reqHeader: x-edgefunction-request, exists: false } # skip loopback requests to prevent infinite loops
        action:
          type: selectAemOrigin
          originName: edgefunction-my-edge-function # edgefunction-<name-of-the-function>

如果任何條件失敗,要求絕不會到達您的AEM Edge函式。 從最少的函式需求條件開始,僅新增更多以讓路由更精確。 如需所有支援的屬性和運運算元,請參閱來源選取器

實作處理常式

每個AEM Edge函式都會註冊擷取事件處理常式。 使用處理常式在要求到達來源之前調整要求、在回應到達使用者端之前修改回應,或兩者皆調整。

下列程式碼片段示範AEM Edge函式中的請求篩選與回應修改。

// src/index.js
addEventListener("fetch", (event) => event.respondWith(handleRequest(event)));

async function handleRequest(event) {
  const req = event.request;
  const url = new URL(req.url);

  try {
    // ------------------------------------------------------------
    // --- Request filtering: adjust before origin ---
    // ------------------------------------------------------------

    // Example: Rewrite origin, path, or query
    // Replace origin based on some criteria such as path or query
    const newOriginRequest = new Request(`https://origin.example.com${url.pathname}${url.search}`);
    const newOriginResponse = await fetch(newOriginRequest);
    // Return the new origin response
    return newOriginResponse;

    ...

    // Example: Rewrite request headers before reaching the origin
    // Add or modify headers before the request reaches the origin, like adding an authorization token based on exchange with an external service.
    const originRequest = new Request(req, {
      headers: new Headers({ ...Object.fromEntries(req.headers), "Authorization": "Bearer <token>" }),
    });
    const originResponse = await fetch(originRequest);
    return originResponse;

    ...

    // ------------------------------------------------------------
    // --- Response filtering: modify before client ---
    // ------------------------------------------------------------

    // Example: Change response HTML (fetch from origin, transform the body)
    // Fetch the response from the origin, transform the body, and return the transformed response.
    const originRequest = new Request(`https://origin.example.com${url.pathname}`);
    const originResponse = await fetch(originRequest);
    const transformedHtml = transformHtml(await originResponse.text());
    return new Response(transformedHtml, { status: 200, headers: originResponse.headers });

    ...

    // Example: Redirect at the edge
    // Redirect the client to a new path, like a legacy URL to a new URL.
    return Response.redirect("https://www.example.com/new-path", 301);

    ...

    // Example: Personalize by request context (geo, device, or audience)
    // Fetch the response from the origin, personalize the body, and return the personalized response.
    const originRequest = new Request(`https://origin.example.com${url.pathname}`);
    const originResponse = await fetch(originRequest);
    const personalizedHtml = personalizeHtml(await originResponse.text());
    return new Response(personalizedHtml, { status: 200, headers: originResponse.headers });

    return new Response("Not implemented", { status: 501 });
  } catch (err) {
    console.log(err);
    return new Response("Error", { status: 500 });
  }
}

要點:

概念
詳細資料
CDN篩選器
cdn.yaml路由中的when + allOf僅符合您的AEM Edge函式的流量
要求篩選
fetch()到來源之前建置具有不同來源、路徑、查詢或標題的新Request
回應篩選
傳回含有轉換HTML、重新導向或個人化內容的新Response
CDN回送
在內部fetch()呼叫上設定Sentinel標頭,讓CDN將回送流量路由到來源

設計准則

  • 儘可能縮小篩選範圍。
  • 將導覽功能限製為GETHEAD
  • 透過在內部fetch()呼叫上設定Sentinel標頭,避免CDN回圈上的無限回圈。
  • 透過您的Cloud Manager設定管道部署更新的cdn.yaml

防止CDN回圈上的無限回圈

當AEM Edge函式透過CDN從來源擷取內容時,可能會發生無限回圈。 該擷取作業會重新進入CDN、符合相同的原始選取器規則,然後路由回到函式。

若要防止此情況,您可以設定Sentinel (例如,x-edgefunction-request)標頭,從來源選擇器規則中排除回送請求。 初始訪客請求沒有標頭,但卻達到了AEM Edge功能。 回送要求會攜帶標頭、讓條件失敗,並改路由傳送到來源。

下列程式碼和設定程式碼片段示範如何防止CDN迴路發生無限回圈。

// src/index.js
addEventListener("fetch", (event) => event.respondWith(handleRequest(event)));
...

// In the handler: set the sentinel on the loopback fetch
const loopbackRequest = new Request(`https://www.example.com${url.pathname}`, {
  headers: { "x-edgefunction-request": "true" },
});
await fetch(loopbackRequest);

請參閱AEM Edge函式範例,以瞭解如何在AEM Edge函式處理常式中設定Sentinel標頭。

# config/cdn.yaml (origin selector excerpt)
kind: "CDN"
version: "1"
data:
  originSelectors:
    rules:
      - name: route-to-edge-function
        when:
          allOf:
            ...
            - { reqHeader: x-edgefunction-request, exists: false } # skip loopback requests to prevent infinite loops
            ...

請參閱AEM Edge函式範例,以瞭解如何在CDN設定中排除已含有Sentinel標頭的請求。

完整範例

AEM Edge函式範例存放庫包含具有完整config/cdn.yaml規則的攔截器函式:

範例
存放庫
它顯示的內容
AEM as a Cloud Service HTML轉換器
publish-delivery-transformer
AEM as a Cloud Service​網站的發佈頁面篩選器,會將JavaScript片段插入HTML回應中並防止CDN回送
Edge Delivery HTML轉換器
edge-delivery-transformer
將網站頁首和頁尾插入Edge Delivery Services回應中的​ HTML ​網站的發佈頁面篩選器
重新導向地圖查閱
publish-delivery-redirect-map
重新導向至舊版URL並防止CDN回送的GET/HEAD頁面篩選器

其他資源

recommendation-more-help
experience-manager-learn-help-cloud-service