将Cloud Front自定义域URL传递给lambda

时间:2018-11-16 06:58:00

标签: node.js aws-lambda aws-api-gateway amazon-cloudfront

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

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

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

被调用的lambda必须返回响应,并将某些路径/查询参数附加到json主体中的自定义域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启用标头。 lambda事件中的主机提供API网关URL。有没有办法在lambda中获得自定义域的映射?

我的用于自定义域的云形成模板如下

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

2 个答案:

答案 0 :(得分:0)

在将API Gateway + 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"
  }
}

答案 1 :(得分:0)

感谢@thomasmichaelwallace指向AWS论坛上的my post,该方法说明了使用Lambda @ Edge Origin Request触发器将原始请求Host头注入备用请求头的方法。这是一种解决方案,但需要Lambda触发器,因此存在额外的开销和成本。该解决方案实际上是关于可处理多个域名的CloudFront分发,但需要向后端应用程序发送一个Host头,同时向应用程序警告另一个请求头(我随意称为X-Forwarded-Host

还有其他选择。

如果CloudFront分发仅处理一个传入的主机名,则只需配置静态custom origin header。它们由CloudFront无条件地注入到请求中(如果原始请求者设置了这样的标头,则在注入配置的标头之前将其删除)。设置X-Forwarded-Host: api.example.com,它将被注入所有请求并在API Gateway上可见。

这是最简单的解决方案,根据问题所在,它应该可以工作。

但是直观的解决方案不起作用-您不能简单地将Host标头列入白名单以转发到源,因为这不是API Gateway所期望的。

但是应该有一种使其期望该标头的方式。

以下内容基于许多独立且准确的观察结果,但我并未一起进行测试。这是主意:

  • 使用区域API网关部署,而不是Edge-Optimized。在使用自己的CloudFront发行版时,您无论如何都不希望进行边缘优化的部署,因为这会通过冗余地通过CloudFront网络发送请求而增加延迟。在此设置中也将无法使用。
  • 将您的API配置为自定义域(针对您的公开域)
  • 将适当的证书附加到API网关,但是
  • 执行,将DNS指向分配的区域域名API网关为您提供;相反,
  • 使用分配的区域端点主机名作为CloudFront中的原始域名
  • 将主机标头列入白名单以进行转发

应该之所以有效,是因为它将导致API网关期望原始的Host标头,以及Host标头时CloudFront处理后端TLS的方式已列入转发白名单。