问题
I have a serverless website on AWS S3. But S3 have a limitation that I want to overcome: it don't allow me to have friendly URLs.
For example, I would like to replace URL:
www.mywebsite.com/user.html?login=daniel
With this URL friendly:
www.mywebsite.com/user/daniel
So, I would like to know if I can use Lambda together with API Gateway to achieve this.
My idea is:
API Gateway ---> Lambda function ---> fetch S3 resource
The API Gateway will get ANY request, and pass information to a Lambda funcion, that will process some logic using the request URL (including maybe some database query) and then fetch the resource from S3.
I know AWS API Gateway main purpose is to be a gateway to REST APIs, but can we also use it as a proxy to an entire website?
回答1:
The good option can be to use CloudFront as a reverse proxy, you can use Viewer/Origin response request to trigger lambda and fetch the resource from S3.
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-examples.html
https://aws.amazon.com/blogs/networking-and-content-delivery/amazon-s3-amazon-cloudfront-a-match-made-in-the-cloud/
回答2:
It is possible to use API Gateway as a reverse proxy for a S3 website.
I was able to do that following steps below:
- In AWS API Gateway, create a "proxy resource" with resource path = "{proxy+}"
- Go to AWS Certificate Manager and request a wildcard certificate for your website (*.mywebsite.com)
- AWS will tell you to create a CNAME record in you domain registrar, to verify that you own that domain
- After your certificate is validated, go to AWS API Gateway and create a Custom Domain Name (click on "Custom Domain Names" and then "Create Custom Domain Name"). In "domain name" type your domain (www.mywebsite.com) and select the ACM Certificate that you just created (step 1 above). Create a "Base Path Mapping" with path = "/" and in "destination" select your API and stage.
- After that, you will need to add another CNAME record, with the CloudFront "Target Domain Name" that was generated for that Custom Domain Name.
In the Lambda, we can route the requests:
'use strict';
const AWS = require('aws-sdk');
const s3 = new AWS.S3();
const myBucket = 'myBucket';
exports.handler = async (event) => {
var responseBody = "";
if (event.path=="/") {
responseBody = "<h1>My Landing Page</h1>";
responseBody += "<a href='/xpto'>link to another page</a>";
return buildResponse(200, responseBody);
}
if (event.path=="/xpto") {
responseBody = "<h1>Another Page</h1>";
responseBody += "<a href='/'>home</a>";
return buildResponse(200, responseBody);
}
if (event.path=="/my-s3-resource") {
var params = {
Bucket: myBucket,
Key: 'path/to/my-s3-resource.html',
};
const data = await s3.getObject(params).promise();
return buildResponse(200, data.Body.toString('utf-8'));
}
return buildResponse(404, '404 Error');
};
function buildResponse(statusCode, responseBody) {
var response = {
"isBase64Encoded": false,
"statusCode": statusCode,
"headers": {
"Content-Type" : "text/html; charset=utf-8"
},
"body": responseBody,
};
return response;
}
回答3:
A good bet would be to use CloudFront and Lambda@Edge.
Lambda@Edge allows you to run Lambda function in the edge location of the CloudFront CDN network.
CloudFront gives you the option to hook into various events during its lifecycle and apply logic.
This article looks like it might be describing something similar to what you're talking about.
https://aws.amazon.com/blogs/networking-and-content-delivery/implementing-default-directory-indexes-in-amazon-s3-backed-amazon-cloudfront-origins-using-lambdaedge/
来源:https://stackoverflow.com/questions/57764866/can-i-use-aws-api-gateway-as-a-reverse-proxy-for-a-s3-website