使用Cloudformation创建AWS Api Gateway代理资源?

12

我正在尝试从API Gateway端点代理配置为网站的S3存储桶。我已经成功地使用控制台配置了端点,但是我无法使用Cloudformation重新创建该配置。

在大量的尝试和猜测之后,我得出了以下CF堆栈模板,它使我接近成功:

Resources:
  Api:
    Type: 'AWS::ApiGateway::RestApi'
    Properties:
      Name: ApiDocs

  Resource:
    Type: 'AWS::ApiGateway::Resource'
    Properties:
      ParentId: !GetAtt Api.RootResourceId
      RestApiId: !Ref Api
      PathPart: '{proxy+}'

  RootMethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      HttpMethod: ANY
      ResourceId: !GetAtt Api.RootResourceId
      RestApiId: !Ref Api
      AuthorizationType: NONE
      Integration:
        IntegrationHttpMethod: ANY
        Type: HTTP_PROXY
        Uri: 'http://my-bucket.s3-website-${AWS::Region}.amazonaws.com/'
        PassthroughBehavior: WHEN_NO_MATCH
        IntegrationResponses:
          - StatusCode: 200

  ProxyMethod:
    Type: 'AWS::ApiGateway::Method'
    Properties:
      HttpMethod: ANY
      ResourceId: !Ref Resource
      RestApiId: !Ref Api
      AuthorizationType: NONE
      RequestParameters:
        method.request.path.proxy: true
      Integration:
        CacheKeyParameters:
          - 'method.request.path.proxy'
        RequestParameters:
          integration.request.path.proxy: 'method.request.path.proxy'
        IntegrationHttpMethod: ANY
        Type: HTTP_PROXY
        Uri: 'http://my-bucket.s3-website-${AWS::Region}.amazonaws.com/{proxy}'
        PassthroughBehavior: WHEN_NO_MATCH
        IntegrationResponses:
          - StatusCode: 200

  Deployment:
    DependsOn:
      - RootMethod
      - ProxyMethod
    Type: 'AWS::ApiGateway::Deployment'
    Properties:
      RestApiId: !Ref Api
      StageName: dev

使用这个模板,我可以成功获取存储桶网站的根目录,但代理资源却返回500错误:

curl -i https://abcdef.execute-api.eu-west-1.amazonaws.com/dev/index.html
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
Content-Length: 36
Connection: keep-alive
Date: Mon, 11 Dec 2017 16:36:02 GMT
x-amzn-RequestId: 6014a809-de91-11e7-95e4-dda6e24d156a
X-Cache: Error from cloudfront
Via: 1.1 8f6f9aba914cc74bcbbf3c57e10df26a.cloudfront.net (CloudFront)
X-Amz-Cf-Id: TlOCX3eemHfY0aiVk9MLCp4qFzUEn5I0QUTIPkh14o6-nh7YAfUn5Q==

{"message": "Internal server error"}

我不知道如何调试那个 500 错误。

为了追踪问题,我将手动在控制台创建的资源(正常工作)与 Cloudformation 创建的资源(不正常工作)上运行aws apigateway get-resource命令进行比较。这些资源看起来完全一样。然而,get-method的输出略有不同,我不确定使用 Cloudformation 是否可能使它们完全相同。

正常工作的方法配置:

{
  "apiKeyRequired": false,
  "httpMethod": "ANY",
  "methodIntegration": {
    "integrationResponses": {
      "200": {
        "responseTemplates": {
          "application/json": null
        },
        "statusCode": "200"
      }
    },
    "passthroughBehavior": "WHEN_NO_MATCH",
    "cacheKeyParameters": [
      "method.request.path.proxy"
    ],
    "requestParameters": {
      "integration.request.path.proxy": "method.request.path.proxy"
    },
    "uri": "http://muybucket.s3-website-eu-west-1.amazonaws.com/{proxy}",
    "httpMethod": "ANY",
    "cacheNamespace": "abcdefg",
    "type": "HTTP_PROXY"
  },
  "requestParameters": {
    "method.request.path.proxy": true
  },
  "authorizationType": "NONE"
}

不能正常工作的配置:

{
    "apiKeyRequired": false,
    "httpMethod": "ANY",
    "methodIntegration": {
        "integrationResponses": {
            "200": {
                "responseParameters": {},
                "responseTemplates": {},
                "statusCode": "200"
            }
        },
        "passthroughBehavior": "WHEN_NO_MATCH",
        "cacheKeyParameters": [
            "method.request.path.proxy"
        ],
        "requestParameters": {
            "integration.request.path.proxy": "method.request.path.proxy"
        },
        "uri": "http://mybucket.s3-website-eu-west-1.amazonaws.com/{proxy}",
        "httpMethod": "ANY",
        "requestTemplates": {},
        "cacheNamespace": "abcdef",
        "type": "HTTP_PROXY"
    },
    "requestParameters": {
        "method.request.path.proxy": true
    },
    "requestModels": {},
    "authorizationType": "NONE"
}

区别:

  • 可工作的配置将responseTemplates设置为"application/json": null。据我所知,无法使用Cloudformation显式地将映射设置为null。我的CF方法在此处只有一个空对象。
  • 我的CF方法具有"responseParameters": {},而可工作的配置根本没有responseParameters
  • 我的CF方法具有"requestModels": {},而可工作的配置根本没有requestModels

在控制台中比较这两个配置,它们看起来完全相同。

我已经不知道该怎么办了:我做错了什么?是否可能使用Cloudformation实现这个目标?


你尝试在API网关控制台中打开API的详细日志记录了吗?也许它可以给你更多的细节。 - arjabbar
1
嗯,所以我删除了我的堆栈并从头开始重新启动它,现在它可以工作了。所以我想通过一系列的微小调整从起点到此并不真正起作用。不能真正说明它。无论如何,这篇文章现在记录了正确设置的方法 :) - Christian Johansen
1个回答

4

回答:以上是正确的。我通过一系列步骤得出了这个解决方案,并反复应用模板。使用此配置删除堆栈并重新部署它可以产生所需的效果。


3
这是因为对现有API网关的任何更新都需要重新部署API网关,即使使用CloudFormation也是如此。CloudFormation只会在API全新时才会部署它。 - JamesQMurphy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接