通过 APIGateway 通过 HTTPS 从 S3 存储桶渲染 JPG 图像

问题描述 投票:0回答:1

我有一个 Cloudformation 模板,它通过 API 网关通过 HTTPS 提供 S3 文本和二进制内容(

mp3
jpeg
png
)。

我有一系列

hello
资产(
json
mp3
jpg
),我将它们推送到 S3 存储桶,并小心地为每个资产添加正确的
MIME
类型。

然后我转到浏览器查看是否可以通过 HTTPS 访问资源。

hello.json
工作正常;我可以在浏览器屏幕中看到
{"hello": "world"}

hello.mp3
也能正常工作;浏览器呈现一个 mp3 播放器,我可以听到“hello world”的声音。

但是

hello.jpg
呈现出破碎的图像:/


我的第一个想法是图像本身被破坏了;但我可以

curl
将其保存到本地文件,浏览器将很好地呈现文件图像。

我的第二个想法是,浏览器和 API 网关之间在原始二进制数据与 Base64 编码二进制数据方面存在一些混淆;我知道 API Gateway 有时喜欢渲染 b64 数据。

看来这里确实有些混淆。

jpeg
原始文件的长度是1467字节,但是如果我检查Chrome Javascript控制台,服务器似乎响应长度超过1900。我认为服务器可能因此返回b64数据,因为我知道b64文件通常是大约比原始文件大 1/3。

那么我认为 HTTP 请求标头可能会影响响应类型。但无论我给

Accept
提供什么
curl
标头值,服务器始终返回 1467
Content-Length
。我无法让
curl
复制浏览器对服务器所做的事情。

我也很困惑为什么浏览器会愉快地渲染

mp3
文件,而不是来自同一端点的
jpg
文件。

对于如何解决这个问题有什么想法吗?谢谢你。

---
Outputs: {}
Parameters:
  AppName:
    Type: String
  DomainName:
    Type: String
  CertificateArn:
    Type: String
  MemorySizeDefault:
    Default: '512'
    Type: String
  RuntimeVersion:
    Default: '3.10'
    Type: String
  TimeoutDefault:
    Default: '5'
    Type: String
Resources:
  MyWebsite:
    Properties:
      BucketName: !Sub "${AppName}-bucket"
    Type: AWS::S3::Bucket
  MyWebsiteDeployment:
    DependsOn:
    - MyWebsiteMethod
    Properties:
      RestApiId:
        Ref: MyWebsiteRestApi
    Type: AWS::ApiGateway::Deployment
  MyWebsiteDomain:
    Properties:
      CertificateArn:
        Ref: CertificateArn
      DomainName:
        Ref: DomainName
    Type: AWS::ApiGateway::DomainName
  MyWebsiteDomainPathMapping:
    DependsOn:
    - MyWebsiteDomain
    Properties:
      DomainName:
        Ref: DomainName
      RestApiId:
        Ref: MyWebsiteRestApi
      Stage: prod
    Type: AWS::ApiGateway::BasePathMapping
  MyWebsiteDomainRecordSet:
    Properties:
      AliasTarget:
        DNSName:
          Fn::GetAtt:
          - MyWebsiteDomain
          - DistributionDomainName
        EvaluateTargetHealth: false
        HostedZoneId:
          Fn::GetAtt:
          - MyWebsiteDomain
          - DistributionHostedZoneId
      HostedZoneName:
        Fn::Sub:
        - ${prefix}.${suffix}.
        - prefix:
            Fn::Select:
            - 1
            - Fn::Split:
              - .
              - Ref: DomainName
          suffix:
            Fn::Select:
            - 2
            - Fn::Split:
              - .
              - Ref: DomainName
      Name:
        Ref: DomainName
      Type: A
    Type: AWS::Route53::RecordSet
  MyWebsiteMethod:
    Properties:
      AuthorizationType: NONE
      HttpMethod: GET
      Integration:
        Credentials:
          Fn::GetAtt:
          - MyWebsiteRole
          - Arn
        IntegrationHttpMethod: ANY
        IntegrationResponses:
        - ResponseParameters:
            method.response.header.Content-Type: integration.response.header.Content-Type
          StatusCode: 200
        - SelectionPattern: '404'
          StatusCode: 404
        PassthroughBehavior: WHEN_NO_MATCH
        RequestParameters:
          integration.request.path.proxy: method.request.path.proxy
        Type: AWS
        Uri:
          Fn::Sub: arn:aws:apigateway:${AWS::Region}:s3:path/${MyWebsite}/{proxy}
      MethodResponses:
      - ResponseParameters:
          method.response.header.Content-Type: true
        StatusCode: 200
      - StatusCode: 404
      RequestParameters:
        method.request.path.proxy: true
      ResourceId:
        Ref: MyWebsiteResource
      RestApiId:
        Ref: MyWebsiteRestApi
    Type: AWS::ApiGateway::Method
  MyWebsiteResource:
    Properties:
      ParentId:
        Fn::GetAtt:
        - MyWebsiteRestApi
        - RootResourceId
      PathPart: '{proxy+}'
      RestApiId:
        Ref: MyWebsiteRestApi
    Type: AWS::ApiGateway::Resource
  MyWebsiteRestApi:
    Properties:
      BinaryMediaTypes:
      - audio/mpeg
      - image/jpeg
      - image/x-png
      Name:
        Fn::Sub: my-website-rest-api-${AWS::StackName}
    Type: AWS::ApiGateway::RestApi
  MyWebsiteRole:
    Properties:
      AssumeRolePolicyDocument:
        Statement:
        - Action: sts:AssumeRole
          Effect: Allow
          Principal:
            Service: apigateway.amazonaws.com
        Version: '2012-10-17'
      Policies:
      - PolicyDocument:
          Statement:
          - Action:
            - s3:GetObject
            Effect: Allow
            Resource:
              Fn::Sub: arn:aws:s3:::${MyWebsite}/*
          Version: '2012-10-17'
        PolicyName:
          Fn::Sub: my-website-role-policy-${AWS::StackName}
    Type: AWS::IAM::Role
  MyWebsiteStage:
    Properties:
      DeploymentId:
        Ref: MyWebsiteDeployment
      RestApiId:
        Ref: MyWebsiteRestApi
      StageName: prod
    Type: AWS::ApiGateway::Stage
amazon-web-services amazon-s3 aws-api-gateway
1个回答
0
投票

答案是将

BinaryMediaTypes
中的条目替换为单个条目
*/*

我不知道为什么会这样,但确实如此

答案显然就在这里 -

https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-payload-encodings.html

但这对我来说没有任何意义

无论如何;关闭

© www.soinside.com 2019 - 2024. All rights reserved.