You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建适配CloudFront与AWS API Gateway WebSocket的SAM模板

适配CloudFront与API Gateway WebSocket的SAM实现方案

核心配置避坑要点

  • WebSocket协议依赖HTTP/1.1升级请求与HTTP/2传输,CloudFront必须开启全量HTTP方法(GET/POST/PUT/PATCH/DELETE/OPTIONS/HEAD),分发配置强制选http2版本
  • API Gateway WebSocket源必须使用AllViewerExceptHost托管源请求策略,禁止透传Host头,否则会触发API Gateway域名校验403;缓存策略必须选CachingDisabled托管策略,所有查询参数、请求头、Cookie全量透传,不能丢Sec-WebSocket-Key/Upgrade/Connection这类握手必需头
  • CloudFront的路径匹配规则必须覆盖WebSocket API的部署阶段路径,不要尝试给WebSocket路由加自定义路径改写,CloudFront Functions/Edge@AWS逻辑很容易篡改升级头导致握手失败
  • 给API Gateway源配置专用的OAC(源访问控制),签名协议选sigv4,签名行为选始终签名,避免API端点公网暴露

可直接复用的SAM模板

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: CloudFront + API Gateway WebSocket SAM deployment template

Resources:
  # WebSocket API 核心定义
  AppWebSocketApi:
    Type: AWS::ApiGatewayV2::Api
    Properties:
      Name: AppWebSocketService
      ProtocolType: WEBSOCKET
      RouteSelectionExpression: "$request.body.action"

  # 示例$connect路由与Lambda集成,其余$disconnect/$default/自定义路由可按相同结构扩展
  ConnectRoute:
    Type: AWS::ApiGatewayV2::Route
    Properties:
      ApiId: !Ref AppWebSocketApi
      RouteKey: "$connect"
      Target: !Join [ '/', [ 'integrations', !Ref ConnectIntegration ] ]
  ConnectIntegration:
    Type: AWS::ApiGatewayV2::Integration
    Properties:
      ApiId: !Ref AppWebSocketApi
      IntegrationType: AWS_PROXY
      IntegrationUri: !Sub arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${WsConnectHandler.Arn}/invocations

  # WebSocket 部署阶段
  WsProdStage:
    Type: AWS::ApiGatewayV2::Stage
    Properties:
      ApiId: !Ref AppWebSocketApi
      StageName: prod
      AutoDeploy: true

  # API Gateway 专用源访问控制
  WsOriginOac:
    Type: AWS::CloudFront::OriginAccessControl
    Properties:
      OriginAccessControlConfig:
        Name: WsApiOac
        OriginAccessControlOriginType: apigateway
        SigningBehavior: always
        SigningProtocol: sigv4

  # CloudFront 分发配置
  CdnDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Enabled: true
        HttpVersion: http2
        PriceClass: PriceClass_100
        DefaultCacheBehavior:
          TargetOriginId: StaticAssetOrigin
          ViewerProtocolPolicy: redirect-to-https
          CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6 # 托管CachingOptimized策略,用于静态资源
        CacheBehaviors:
          # WebSocket专属缓存行为
          - PathPattern: "prod/*"
            TargetOriginId: WebSocketApiOrigin
            ViewerProtocolPolicy: https-only
            AllowedMethods: GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE
            CachePolicyId: 4135ea2d-6df8-44a3-9df3-4b5a84be39ad # 托管CachingDisabled策略,禁止缓存WebSocket请求
            OriginRequestPolicyId: b689b0a8-53d0-40ab-baf2-68738e2966ac # 托管AllViewerExceptHost策略
        Origins:
          - Id: WebSocketApiOrigin
            DomainName: !Sub "${AppWebSocketApi}.execute-api.${AWS::Region}.amazonaws.com"
            OriginPath: ""
            OriginAccessControlId: !Ref WsOriginOac
            CustomOriginConfig:
              HTTPSPort: 443
              OriginProtocolPolicy: https-only
              OriginSSLProtocols: [TLSv1.2]
          # 静态资源源(如S3站点)可按需求自行补充
          - Id: StaticAssetOrigin
            # 此处替换为你自己的静态源配置
            DomainName: example-bucket.s3.amazonaws.com
            CustomOriginConfig:
              HTTPSPort: 443
              OriginProtocolPolicy: https-only
              OriginSSLProtocols: [TLSv1.2]

  # 示例连接处理Lambda
  WsConnectHandler:
    Type: AWS::Serverless::Function
    Properties:
      Runtime: nodejs20.x
      Handler: index.handler
      InlineCode: |
        exports.handler = async (event) => {
          // 自定义连接鉴权逻辑写在这里
          return { statusCode: 200 };
        };

部署与排错流程

  • 模板编写完成后,在项目根目录执行sam build构建资源,再执行sam deploy --guided跟着引导完成首次部署,后续更新直接执行sam deploy即可
  • 部署完成后,用wss://<CloudFront分配的域名>/prod作为连接地址测试WebSocket连通性,不要直接调用API Gateway的默认公网端点
  • 常见问题排查:

    握手返回403:先检查源请求策略是否透传了Host头,再核对OAC签名区域与API部署区域是否一致,最后确认CloudFront已开启全量HTTP方法
    连接建立成功但发送消息立即断连:检查WebSocket路径对应的缓存策略是否关闭了缓存,是否有边缘计算逻辑篡改了Upgrade/Connection头
    请求返回404:检查CloudFront路径匹配规则是否正确覆盖WebSocket的阶段路径,确认路径中已携带部署阶段名(示例中为prod)

内容的提问来源于stack exchange,提问作者Ben Mora

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 20:24:09