Building the S3 API in Amazon API Gateway
If you have ever used the Amazon API Gateway to build an application backend, you are probably familiar with most of its integration capabilities, like Lambda functions, other HTTP endpoints like EC2 instances, or even just mock response. But did you know that Amazon API Gateway can also integrate with almost every other AWS service out there?
Since most AWS services expose their own APIs, an API built in API Gateway can simply wrap the service APIs with your own. This has numerous advantages:
- The API Gateway to AWS service integrations are “direct”. There is no Lambda function or other piece of code sitting between the gateway and your intended service.
- If you have been using Lambda simply as an intermediary to invoke another AWS service from API Gateway, you can do away with this approach and save the extra hop and latency introduced in every request-response cycle.
- Your API in API Gateway can be truly “yours”, down to every detail: the names of your URL endpoints, what parameters they take, the shape (schema) of their request and response bodies, etc.
- This lets you completely abstract away the underlying service API details and its AWS-ness. You can use mapping templates in the gateway to transform the input/output into any format suitable for your end-user apps.
- You can even cherry-pick specific APIs from the AWS service you need and combine them into a single API in API Gateway. This way, from your application’s perspective, it’s simply calling various endpoints under a single API base URL, without knowing how its request is being distributed to several AWS services in the background.
- Authentication: If your app were to invoke AWS service APIs directly, it is forced to use AWS-specific auth techniques. But if you wrap the service APIs in another API in API Gateway, you can add any kind of auth mechanism to it: Cognito, IAM, or even custom Lambda functions.
In this post, we will build a small subset of the S3 API in API Gateway using this “direct service integration” approach, in order to learn how it works.
List All Buckets API
Start by going to the API Gateway console and click Create REST API. Create a new API named MyS3API:
First, we add a GET method to the “/” resource. This will perform the “list all S3 buckets” action. Configure this method as shown below:
Note the execution role used above. This is an IAM role I created earlier. It has the trusted entity of apigateway.amazonaws.com
so API Gateway can assume this role and it has the following permission policies attached: AmazonS3FullAccess
and AmazonAPIGatewayPushToCloudWatchLogs
. This allows API Gateway to perform all S3 actions and also write logs to CloudWatch.
Next, add the 400 and 500 HTTP response status codes to the GET method so our API doesn’t always return the default 200 response:
Next, add the Content-Type
and Content-Length
HTTP headers to the 200 response code:
Now map all 4XX S3 responses to our 400 response code and all 5XX to our 500:
Now create the header mappings. Expand the 200 response and map the headers returned by the S3 response to the ones we created earlier:
Important Note: We are not securing our API with an auth mechanism here because this is just for learning purposes, but if you use this approach in your projects, you’ll definitely need to secure the API using either IAM, Cognito, or Lambda.
If you try testing out the GET method now from the console, you’ll see it works as expected. All buckets are returned in the response:
Also, note that the Content-Type in the response header is correctly set to XML now instead of the default JSON because we mapped the headers accordingly:
Create Bucket API
Add a /{bucket}
resource:
Add a PUT method to it to create buckets:
Notice the path override is set to {bucket}
. Map this to the bucket parameter we get in the request:
Add the Content-Type
header to the Method Request:
Go back to the Integration Request and map the Content-Type
header as we did for the “GET /” resource:
Notice the inclusion of a couple more headers other than Content-Type
. These are S3-specific headers as explained below:
x-amz-acl
sets the ACL for the uploaded object. We set it toauthenticated-read
so only authenticated users with access to this bucket can see the object.- The
Expect
header is set to100-continue
and ensures that the request payload is only submitted when the request parameters are validated.
Now test the API:
The bucket was successfully created!
You can redo the steps in this section to create the GET /{bucket}
and DELETE /{bucket}
API endpoints.
Conclusion
In this article, we created a CRUD API for the S3 service using API Gateway’s native integration with the S3 service. You can follow a similar approach for integrating API Gateway with any other AWS service.
About the Author
Harish KM is an AWS Developer at QloudX. He is passionate about creating zero-maintenance fully-serverless cloud-native solutions in AWS. With 20+ cloud & IT certifications, he is an expert in a multitude of technologies, especially serverless.