【问题标题】:Lambda@edge not triggered by an origin-request eventLambda@edge 不是由源请求事件触发的
【发布时间】:2020-04-08 07:01:13
【问题描述】:

我正在尝试使用 CloudFormation 配置 Lambda@edge 函数。部署模板后,一切看起来都可以在控制台中找到,但是不会触发监听 origin-request 事件的 lambda 函数。 很奇怪,viewer-request 事件确实会触发一个函数。

我做错了什么?如何使origin-request 事件起作用?

这是我的模板:

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: Deployment of Lambda@edge functions

Parameters:
  Stage:
    Type: String
    AllowedValues:
      - staging
      - production
    Default: staging
    Description: Stage that can be added to resource names
  CodeBucket:
    Type: String
    Description: The S3 Bucket name for latest code upload
  CodeKey:
    Type: String
    Description: The S3 Key for latest code upload

# Mappings:
#   AliasMap:
#     staging:
#       Alias: "staging-app.achrafsouk.com"
#     production:
#       Alias: "app.achrafsouk.com"
Resources:
  CFDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Enabled: true
        Logging:
          Bucket: XXX.s3.amazonaws.com
          IncludeCookies: false
          Prefix: !Sub ${Stage}
        PriceClass: PriceClass_100
        Comment:
          !Sub "Lambda@Edge - ${Stage}"
          # Aliases:
          #   - !FindInMap [AliasMap,
          # Ref: Stage, Alias]
        Origins:
          - CustomOriginConfig:
              OriginProtocolPolicy: https-only
            DomainName: !Sub "${Stage}.defaultOrigin.example.com"
            Id: defaultOrigin
            OriginCustomHeaders:
              - HeaderName: X-Node-Env
                HeaderValue: !Sub "${Stage}"
          - CustomOriginConfig:
              OriginProtocolPolicy: https-only
            DomainName: !Sub "${Stage}.another.example.com"
            Id: rateLimitsOrigin
            OriginCustomHeaders:
              - HeaderName: X-Node-Env
                HeaderValue: !Sub "${Stage}"
        DefaultCacheBehavior:
          ForwardedValues:
            Headers:
              - CloudFront-Viewer-Country
              - X-Request-Host
              - User-Agent
            QueryString: true
          ViewerProtocolPolicy: https-only
          TargetOriginId: defaultOrigin
          DefaultTTL: 0
          MaxTTL: 0
          LambdaFunctionAssociations:
            # - EventType: viewer-request
            #   LambdaFunctionARN:
            #     Ref: ViewerRequestLambdaFunction.Version
            - EventType: origin-request
              LambdaFunctionARN:
                Ref: OriginRequestLambdaFunction.Version
        CacheBehaviors:
          - ForwardedValues:
              Headers:
                - CloudFront-Viewer-Country
                - X-Request-Host
                - User-Agent
              QueryString: true
            ViewerProtocolPolicy: https-only
            DefaultTTL: 60
            MaxTTL: 60
            TargetOriginId: rateLimitsOrigin
            PathPattern: "/rate-limit*"
            LambdaFunctionAssociations:
              - EventType: origin-request
                LambdaFunctionARN:
                  Ref: GetRateLimitLambdaFunction.Version

  # ViewerRequestLambdaFunction:
  #   Type: AWS::Serverless::Function
  #   Properties:
  #     CodeUri:
  #       Bucket: !Sub ${CodeBucket}
  #       Key: !Sub ${CodeKey}
  #     Role: !GetAtt LambdaEdgeFunctionRole.Arn
  #     Runtime: nodejs10.x
  #     Handler: src/functions/viewerRequest.handler
  #     Timeout: 5
  #     AutoPublishAlias: live
  OriginRequestLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri:
        Bucket: !Sub ${CodeBucket}
        Key: !Sub ${CodeKey}
      Role: !GetAtt LambdaEdgeFunctionRole.Arn
      Runtime: nodejs10.x
      Handler: src/functions/originRequest.handler
      Timeout: 5
      AutoPublishAlias: live
  GetRateLimitLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri:
        Bucket: !Sub ${CodeBucket}
        Key: !Sub ${CodeKey}
      Role: !GetAtt LambdaEdgeFunctionRole.Arn
      Runtime: nodejs10.x
      Handler: src/functions/getRateLimit.handler
      Timeout: 5
      AutoPublishAlias: live

  LambdaEdgeFunctionRole:
    Type: "AWS::IAM::Role"
    Properties:
      Path: "/"
      ManagedPolicyArns:
        - "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: "AllowLambdaServiceToAssumeRole"
            Effect: "Allow"
            Action:
              - "sts:AssumeRole"
            Principal:
              Service:
                - "lambda.amazonaws.com"
                - "edgelambda.amazonaws.com"

Outputs:
  # ViewerRequestLambdaFunctionVersion:
  #   Value: !Ref ViewerRequestLambdaFunction.Version

  OriginRequestLambdaFunctionVersion:
    Value: !Ref OriginRequestLambdaFunction.Version

  GetRateLimitLambdaFunctionVersion:
    Value: !Ref GetRateLimitLambdaFunction.Version

  CFDistribution:
    Description: Cloudfront Distribution Domain Name
    Value: !GetAtt CFDistribution.DomainName

【问题讨论】:

    标签: amazon-cloudfront aws-lambda-edge


    【解决方案1】:

    因此,经过数小时的痛苦试验和错误,解决方案正让我眼前一亮: CloudFront 分配发出错误消息,说它无法连接到源,这是正确的 - 因为我在 CloudFront 分配的源定义中指定了虚拟域。

    我的逻辑是,如果我的 lambda@edge 函数在到达源之前拦截请求,那么源域是否真实都无关紧要。

    事实证明,这是部分正确的。因为它接缝:

    • viewer-request 事件在尝试连接到源之前触发,并且可以通过伪造来触发。
    • origin-request 事件仅在尝试连接到源后才会触发,因此您需要指定一些真实的内容。

    希望我浪费的时间能帮助其他人探索同样的推理路径。

    【讨论】:

    • 非常感谢您浪费的时间。有完全相同的问题 - 谢谢!
    【解决方案2】:

    以防它在将来帮助某人解决此问题 - 我注意到 origin-response(我不小心选择而不是 origin-request)事件(大部分)对我有用,但仍有大量 @987654323 @ 在日志中,并且“按结果类型划分的查看器请求百分比”报告显示错误率很高。

    事实证明它只是在工作,因为我将我的源连接设置为https-only,但我的源(一个空的 s3 存储桶)只接受 http 连接 - 由于某种原因,事件仍在被触发。

    将源连接更改为正确的http-only 完全停止origin-response 工作,直到我还将事件类型更正为origin-request

    因此,一般来说,如果您使用的是 s3 存储桶源,请检查 OriginProtocolPolicy 是否为 http-only。如果它出错了,有时事情可能看起来仍然有效,但并非总是如此,而且您最终会遇到很高的错误率。

    【讨论】:

      猜你喜欢
      • 2020-09-26
      • 2016-06-24
      • 2020-12-08
      • 2011-09-15
      • 2019-03-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多