将云端自定义域 URL 传递给 lambda

passing cloud front custom domain URL to lambda

我有一个自定义域 URL (my-custom-domain.com),REST API 支持查询和路径参数。

https://my-custom-domain.com/hello

https://my-custom-domain.com?firstparam=abc&secondparam=def

调用的 lambda 必须 return 响应,其中一些 path/query 参数附加到 json body 中的自定义域 URL。基本上可以访问的其他资源。

示例: https://my-custom-domain.com/hellofromlambda1123

https://my-custom-domain.com?firstparam=abc&secondparam=yourblogpage&pagenumber=30

一个理想的用例是分页,我必须在其中给出上一个和下一个链接。如何将自定义域 URL 传递给我的 lambda。 我正在研究节点 js 8

在传统的 JAVA 编程中,我们可以通过 HttpServletRequest.getRequestURL() 来实现。 获取自定义域的方法是什么URL。我为 DefaultCacheBehavior 启用了 Headers。 lambda 事件中的主机给出 API 网关 URL。有没有办法在 lambda 中获取自定义域的映射?

自定义域的 My Cloud Formation 模板如下所示

AWSTemplateFormatVersion: '2010-09-09'
Description: Custom domain template

Parameters:
  ServiceName:
    Description: Name of the Service
    Type: String
  DeploymentEnv:
    Default: dev
    Description: The environment this stack is being deployed to.
    Type: String
  CertificateId:
    Description: SSL Certificate Id
    Type: String
  DomainName:
    Description: Name of the custom domain
    Type: String
  HostedZoneId:
    Description: Id of the hosted zone
    Type: String

Resources:
  APIDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Origins:
        - DomainName:  
            Fn::ImportValue:
              !Sub "InvokeURL-${DeploymentEnv}"
          Id: !Sub 'Custom-Domain-${DeploymentEnv}'
          CustomOriginConfig:
            OriginProtocolPolicy: https-only
            OriginSSLProtocols: [TLSv1.2]
        Enabled: 'true'
        DefaultCacheBehavior:
          AllowedMethods:
          - DELETE
          - GET
          - HEAD
          - OPTIONS
          - PATCH
          - POST
          - PUT
          DefaultTTL: 0
          TargetOriginId: !Sub 'Custom-Domain-${DeploymentEnv}'
          ForwardedValues:
            QueryString: 'true'
            Cookies:
              Forward: none
            Headers:
              - 'Accept'
              - 'api-version'
              - 'Authorization'
          ViewerProtocolPolicy: https-only
        Aliases:
          - !Sub '${DomainName}'
        ViewerCertificate:
          AcmCertificateArn: !Sub '${CertificateId}'
          SslSupportMethod: sni-only
          MinimumProtocolVersion: TLSv1.2_2018
  APIDNSRecord:
    Type: AWS::Route53::RecordSet
    DependsOn: "APIDistribution"
    Properties:
      HostedZoneId: !Sub '${HostedZoneId}'
      Comment: DNS name for the custom distribution.
      Name: !Sub '${DomainName}'
      Type: A
      AliasTarget:
        DNSName: !GetAtt APIDistribution.DomainName
        HostedZoneId: Z2FDTNDATAQYW2
        EvaluateTargetHealth: false
Outputs:
  DomainName: 
    Value: !GetAtt APIDistribution.DomainName

当使用 API 网关 + Lambda 和 Lambda Proxy integration 时,lambda 收到的事件包括 headers.Hostheaders.X-Forwarded-Proto 键,它们可以连接起来构建完整的请求url.

例如 https://my-custom-domain.com/hellofromlambda1123

{
  "headers": {
    "Host": "my-custom-domain.com"
    "X-Forwarded-Proto": "https"
  }
}

感谢@thomasmichaelwallace 指向 AWS 论坛上的 my post,该论坛解释了将原始请求 Host header 注入备用请求 header 的方法,使用 Lambda@Edge 源请求触发器。这是一种解决方案,但需要 Lambda 触发器,因此会产生额外的开销和成本。该解决方案实际上是关于处理多个域名的 CloudFront 分配,但需要将单个 Host header 发送到 back-end 应用程序,同时提醒应用程序另一个请求 header ,我随意称之为 X-Forwarded-Host.

还有其他选择。

如果 CloudFront 分配仅处理一个传入主机名,您可以简单地配置一个静态 custom origin header。这些由 CloudFront 无条件地注入到请求中(如果原始请求者设置了这样的 header,它会在注入配置的 header 之前被丢弃)。设置 X-Forwarded-Host: api.example.com 它将被注入所有请求并在 API 网关可见。

这是最简单的解决方案,根据问题内容,​​它应该可行。

但直观的解决方案不起作用——您不能简单地将 Host header 列入白名单以转发到来源,因为那不是 API 网关期待。

但是 应该 有一种方法可以让它期望 header.

以下是基于一些准确、独立的观察结果,但我没有对它们进行综合测试。想法是这样的:

  • 使用区域 API 网关部署,而不是 Edge-Optimized。当您使用自己的 CloudFront 分配时,无论如何您都不需要 edge-optimized 部署,因为这会通过冗余地通过 CloudFront 网络发送请求来增加延迟。它也不会在此设置中工作。
  • 将您的 API 配置为自定义域(针对您的公开域)
  • 将适当的证书附加到 API 网关,但是
  • 做,不做把DNS指向分配的区域域名API网关给你;相反,
  • 使用分配的区域端点主机名作为 CloudFront 中的源域名
  • 将主机 header 列入白名单以进行转发

这个 应该 工作,因为它会导致 API 网关期望原始 Host header,再加上 CloudFront 处理 TLS 的方式在 back-end 上,当 Host header 被列入转发白名单时。