我有一个 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
答案是将
BinaryMediaTypes
中的条目替换为单个条目 */*
我不知道为什么会这样,但确实如此
答案显然就在这里 -
https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-payload-encodings.html
但这对我来说没有任何意义
无论如何;关闭