Create a REST API Endpoint Using AWS Lambda
Create an AWS Lambda function to pull records from a database.
Now that you know your way around API Gateway, you have the power to create vast collections of endpoints. If only we could get those endpoints to actually receive and return some stuff.
We'll create a GET function which will solve the common task of retrieving data from a database. The sequence will look something like:
- Connect to the database
- Execute the relevant SQL query
- Map values returned by the query to a key/value dictionary
- Return a response body containing the prepared response
To get started, create a project on your local machine (this is necessary as we'll need to upload a library to import). We're ultimately going to have 3 items:
- rds_config.py: Credentials for your RDS database
- lambda_function.py: The main logic of your function, via the 'handler'
- pymysql: A lightweight Python library to run SQL queries
Storing Credentials Like an Idiot
For the sake of this tutorial and to avoid a security best-practices tangent, I'm going to do something very bad: store credentials in plain text. Don't ever do this: there are much better ways to handle secrets like these, such as using AWS Secrets Manager.
The Holy lambda_function.py
This is where the magic happens. For this GET call, we're simply going to get all records from a table in a database and return them in a consumable way for whomever will ultimately use the API.
Remember that Lambda expects you to specify the function upon initialization. This can be set in the "Handler" field here:
Let's build this thing:
Check out what's happening in our handler function. We're:
- Establishing a DB connection
- Running a select all query for a table in our database
- Iterating over each row returned by the query
- Mapping values to a dict
- Appending each generated dict to an array
- Returning the array as our response body
The shitty thing about the AWS console is there's no way to install python libraries via the UI, so we need to do this locally. In your project folder, install PyMySQL by using something like
$ venv lambdaenv $ . lambdaenv/bin/activate $ pip3 install pymysql
That will install the pymysql library in your environment bin. Copy that into your main directory where lambda_function.py lives.
In your project folder, make a zip file of lambda_function.py, rds_config.py, and PyMySQL. Upload your ZIP file via the "Code entry type" field:
Save your function and run a test via the top right menu. When asked to specify a test type, select a standard API call. Your results should look like this:
Creating a POST function isn't much more complicated. Obviously we're essentially doing the reverse of before: we're expecting information to be passed, which we'll add to a database.
Parameters in a post function are contained in the event parameter we pass tot he handler. We first create a dict to associate these values. Pay attention to how we structured our sql query for best PyMySQL best practice.
Post functions expect a response body to contain (at the very least) a status code as well as a body. We'll stick to bare minimums here and tell the user is good to go, and recap what was added.
For the sake of this demo we kept things simple with an insert query, but keep in mind this means the same record can never be added twice or updated in this manner- you might be better suited by something such as
REPLACE. Just something to keep in mind as you're building your app.