英文:
Is it possible to use the same domain for API Gateway and Static S3 bucket behind a Cloudfront distribution?
问题
我目前正在AWS中创建一个反馈应用程序。我已经将后端部署在Lambda中,它与API Gateway连接,前端部分由位于Cloudfront分发后面的静态S3存储桶提供服务。
我想在API Gateway上启用TLS 1.2,但似乎只能通过Cloudfront实现。我还想能够在与S3存储桶不同路径但相同域名下提供服务。目前,S3存储桶位于feedback.domain.com。我以前将自定义域名绑定到API Gateway的api.feedback.domain.com上,这在我通过Postman进行请求时有效。但是,当我通过S3存储桶页面上的JavaScript进行请求时,它从不起作用,我会收到CORS错误。如果这是更可行的解决方案,我愿意使用它,但我需要提出有关CORS的另一个问题。
我希望API Gateway位于feedback.domain.com/api,因为据我所知,使用与发出请求的页面相同的域名应该解决CORS问题。我尝试了以下设置,但无法使其正常工作。
当我浏览feedback.domain.com/api时,我看到了我在Cloudfront中设置的错误页面。我尝试创建了一个使Cloudfront分发缓存失效的操作,但这并没有改变任何事情。
我修改了设置,使S3存储桶的源路径为/web/*,但随后到处都会出现AccessDenied错误。
非常感谢提供智慧建议的任何人:)
更新:
以下是我的API阶段的Cloudwatch日志。我访问feedback.domain.com/api时,会收到一个403错误,其中包含我在Cloudfront中定义的自定义错误页面,但在Cloudwatch中没有日志记录:
@Caldazar注意,您提到403意味着我正在访问API,但如果我访问无效的URL,如feedback.domain.com/IDoNotExist,我仍然会收到403错误。我认为这与S3有关?
英文:
I'm currently creating a feedback app in AWS. I have the backend in Lambda which is connected to API Gateway and the frontend of it is served by a Static S3 bucket behind a Cloudfront distribution.
I would like to enable TLS 1.2 on the API Gateway, however, this only seems possible via Cloudfront. I also want to be able to serve it on the same domain name but a different path as the S3 bucket. Currently, the S3 bucket sits on feedback.domain.com. I did have a custom dodmain hooked up to the API Gateway on api.feedback.domain.com, which would work when I made requests to it via Postman. However, when I made requests via the JavaScript on the S3 bucket pages, it would never work and I'd get a CORS error. I am happy to use this if more viable but I would need to ask another question about CORS.
I would like to get the API Gateway to sit on feedback.domain.com/api, because as far as I know, using the same domain as the page making the request should overcome CORS. I've tried the below setup but cannot get this to work.

When I browse to feedback.domain.com/api, I get the error page I set up in Cloudfront. I've tried creating an invalidation so it has cleared the cache on the Cloudfront distribution, but this hasn't changed anything.
I modified the setup so the S3 bucket's origin path was /web/* however i then proceed to get AccessDenied errors everywhere
Setup:

Thank you in advance to anyone that can offer their wise wisdom ![]()
UPDATE:
Below are my Cloudwatch Logs for the API stage. I go to feedback.domain.com/api, get a 403 error with my custom error page defined in Cloudfront, but no log in Cloudwatch: 
A note to @Caldazar, You mention 403 means I'm hitting the API, however, if I go to a none-valid url, feedback.domain.com/IDoNotExist I still get a 403 error. I believe this is something to do with S3?

答案1
得分: 1
问题出在你的Origin path上。
实际上,Origin path的值是在将请求发送到源时将附加到请求的内容。例如,对https://example.com/api/test的请求将导致发送到https://example.com/api/*/api/test的请求。
对于API Gateway,你的Origin path应该是你的API阶段,例如/dev,/prod...
你应该创建额外的behavior,其路径模式应为/api/*,并且Origin设置为你上面创建的API origin。
由于你的路径中有/api/,这样的路径不会正确匹配到你在API Gateway中的路径。为了处理这个问题,你应该将一个CloudFront Function添加到上面创建的API behavior中,作为Viewer request的一部分。CloudFront Functions位于Edit behavior页面的底部。这个函数应该将/api更改为/。以下是我在这种情况下可行的代码:
function handler(event) {
var request = event.request;
var uri = request.uri;
// Check whether the URI starts with "api"
if (uri.startsWith('/api/')) {
request.uri = uri.replace('/api/', '/');
}
return request;
}
基于新的详细信息进行编辑:
为了访问API,你不能进入/api。你的行为设置是仅当你的路径为/api/*时才转发到API Gateway,这意味着只有当你访问像feedback.domain.com/api/mymethod这样的URL时才会触发。
至于第二部分,如果文件不存在,S3将返回403代码,因为有可能文件实际上存在,但用户没有权限查看该文件。
英文:
The problem is in your Origin path.
The Origin path value is actually what will be appended to your request when it's sent to the origin. For example, a request to https://example.com/api/test would result in a request being sent to https://example.com/api/*/api/test
For API Gateway, your Origin path should be your API stage, for example /dev, /prod...
You should create additional behavior that would have Path pattern /api/* and Origin set to your API origin that you created above.
Since you would have /api/ in your path, this wouldn't be matched properly to the path you have in API Gateway. To deal with that, you should add a CloudFront Function to your API behavior created above as part of the Viewer request. CloudFront Functions are at the bottom of the Edit behavior page. This function should change /api to /. This is code that works for me for such situations:
function handler(event) {
var request = event.request;
var uri = request.uri;
// Check whether the URI starts with "api"
if (uri.startsWith('/api/')) {
request.uri = uri.replace('/api/', '/');
}
return request;
}
Edit based on new details:
In order to hit the API, you cannot go to /api. You behaviour is set to forward to API Gateway only if your path is /api/* which means, only if you go to a URL like feedback.domain.com/api/mymethod.
As for the second part, S3 will return 403 code if a file does not exist, because there's a possibility that a file actually exists, but your user does not have permission to see the file.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。








评论