跳转至

CloudFront + API Gateway

設定 API Gateway (後端) 的 CloudFront 行為

當 CloudFront 處理 API Gateway 的請求 時,它 不能快取 API 回應,而且應該允許所有請求 Headers 傳遞到 API Gateway。

設定 Cache Policy

CloudFront 也托管靜態網站 (S3),但 API Gateway 只處理 /api/ 需要 /api/ 避免影響其他路徑

API Gateway 的行為 (**/api/***) 設定:

  • Cache Policy: Managed-CachingDisabled

    • API 不應該快取,因為 API 回應是動態的。
  • Origin Request Policy: Managed-AllViewerExceptHostHeader

    • 允許 CloudFront 傳遞 Headers 和 Query Strings 給 API Gateway。

    • 確保 AuthorizationContent-Type Headers 不會被 CloudFront 過濾掉。

Origin Request Policy 沒辦法選擇 Managed-AllViewerExceptHostHeader

可以選擇 AllViewerExceptHostHeader(這是 CloudFront 預設的類似選項)

  • 允許 CloudFront 傳遞所有 Viewer Headers (除 Host Header)

  • 適合 API Gateway,確保 AuthorizationContent-Type Headers 不會被 CloudFront 過濾掉。

403

可能是因為 CloudFront 目前不允許 **POST****PUT****DELETE** 等非 **GET**/**HEAD** 請求,這通常發生在 CloudFront 連接 API Gateway

403 ERROR
The request could not be satisfied.
This distribution is not configured to allow the HTTP request method that was used for this request. The distribution supports only cachable requests. We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.
Generated by cloudfront (CloudFront)

405

CloudFront 更改 /api/* Edit behavior - Allowed HTTP methods

<?xml version="1.0" encoding="UTF-8"?>
<Error>
    <Code>MethodNotAllowed</Code>
    <Message>The specified method is not allowed against this resource.</Message>
    <Method>POST</Method>
    <ResourceType>OBJECT</ResourceType>
    <RequestId>PNSTKQ6Y2RSGGW24</RequestId>
    <HostId>KZDiN7cGjXzDgkqSGZaxHSTMgHFILesWFZH89yEhyXlqMbbFuiE7ARUdikuDy5aQu+sX2W0RRNY=</HostId>
</Error>

API Gateway 直連成功,但 CloudFront 返回 405 Method Not Allowed,表示 CloudFront 沒有正確將 POST 請求轉發給 API Gateway,可能是 CloudFront Behaviors 設定不完整API Gateway CORS 問題

# 快速測試 CORS 是否有問題
curl -X OPTIONS -H "Origin: CloudFront-domain" -H "Access-Control-Request-Method: POST"  API Gateway
curl -X OPTIONS -H "Origin: https://d2luynvj2paf55.cloudfront.net" -H "Access-Control-Request-Method: POST"  https://xp91hjk4qh.execute-api.ap-southeast-2.amazonaws.com/prod
{"message":"Missing Authentication Token"}

{"message":"Missing Authentication Token"}

這個錯誤通常表示 API Gateway 沒有對應的資源或方法,或者請求未通過授權驗證。 因為你是發送 OPTIONS 方法,這可能與 CORS 設定或 API Gateway 授權方式 有關。

  1. API Gateway 的 OPTIONS 方法沒有正確設置

  2. API Gateway 需要重新部署

  3. OPTIONS 請求被身份驗證攔截(Authorization Issue)

  4. API Gateway 設置 ANY /{proxy+},但沒有獨立處理 OPTIONS

CloudFront

Edit behavior
/api/*

Cache key and origin requests

Cache policy and origin request policy (recommended)

Cache policy:
CachingOptimized

Origin request policy - optional:
AllViewerExceptHostHeader

Response headers policy - optional:
SimpleCORS

API Gateway

/{proxy+} - OPTIONS - Method execution

method.response.header.Access-Control-Allow-Headers:
'Content-Type, Authorization'
method.response.header.Access-Control-Allow-Methods:
'GET, POST, OPTIONS'
method.response.header.Access-Control-Allow-Origin:
'*'

/{proxy+} - POST - Method execution
Integration response:
Proxy integration
Proxy integrations cannot be configured to transform responses.

CORS settings

Access-Control-Allow-Methods:
DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT
Access-Control-Allow-Headers:
Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token
Access-Control-Allow-Origin:
*

frontend

// 確保 axios 設定正確的 base URL 和標頭
let commonURL = "https://你的-cloudfront-網域/api/v1/cry";
axios.defaults.baseURL = commonURL;
axios.defaults.headers.common['Content-Type'] = 'application/json';

backend

@Configuration
public class CorsConfig {
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/**")
                        .allowedOrigins("*")  // 允許所有來源
                        .allowedMethods("GET", "POST", "OPTIONS")  // 與 API Gateway 配置相匹配
                        .allowedHeaders("Content-Type", "Authorization", "X-Amz-Date", 
                                      "X-Api-Key", "X-Amz-Security-Token")
                        .exposedHeaders("Access-Control-Allow-Origin", 
                                      "Access-Control-Allow-Methods")
                        .maxAge(3600);  // 預檢請求快取 1 小時
            }
        };
    }
}

Postman

POST https://d2luynvj2paf55.cloudfront.net/api/v1/cry/encrypt
Content-Type application/json
body
{
    "itemname": "testItem",
    "username": "testUser",
    "password": "testPass"
}

response
405 Method Not Allowed

<?xml version="1.0" encoding="UTF-8"?>
<Error>
    <Code>MethodNotAllowed</Code>
    <Message>The specified method is not allowed against this resource.</Message>
    <Method>POST</Method>
    <ResourceType>OBJECT</ResourceType>
    <RequestId>5DF1BTMVS0R615C7</RequestId>
    <HostId>RgVdX6wRl6Olo5+oyj+LhnqQlL+obbvWC74g+lNvQwQvzbqU4+nyxie0FbVsgJS3PoNWOOe2nbU=</HostId>
</Error>

CloudFront Origin 設定

Origins 需要設置兩個:

Origin 1 (S3 靜態網站):
Origin domain: cry-bucket.s3.ap-southeast-2.amazonaws.com 用於提供前端靜態資源

Origin 2 (API Gateway):
Origin domain: xp91hjk4qh.execute-api.ap-southeast-2.amazonaws.com 用於處理 API 請求

Behaviors 設置兩個規則:

規則 1 (Default *):
Path pattern: Default (*)
Origin: 選擇 Origin 1 (S3)
Allowed HTTP methods: GET, HEAD 用於處理靜態資源請求

規則 2 (/api/*):
Path pattern: /api/*
Origin: 選擇 Origin 2 (API Gateway)
Allowed HTTP methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE 用於處理所有 API 請求 這樣的設置可以讓:

結論

一般的網頁請求 (如 https://your-cloudfront-domain/index.html) 會從 S3 獲取靜態資源

API 請求 (如 https://your-cloudfront-domain/api/v1/cry/encrypt) 會轉發到 API Gateway