Up until now we’ve seen how a very basic AWS Lambda function looks like and how to execute it via the AWS Console. Our donor sign-up function will of course not be triggered from the AWS Console - an HTTP POST request will trigger it.
Looking at it from the architecture standpoint, this is what we want to achieve:
If we transformed it into steps, they would look like so:
POST
request with a JSON payloadevent
argumentOur donor_signup
Lambda function will receive the above JSON payload in the event
argument. Let’s code that!
Because our application will be API-first we should think of a good endpoint schema design - or in simple terms, how
our API URLs will look like.
A good practice is to use nouns to represent resources and verbs to represent actions.
In our case, that resource is the donor
and the action could be signup
(or create
etc.).
I’ll go with /donor/signup
.
But how do we make this happen with Chalice? It’s easier than you might think :)
Replace the content in ~/serverless_workshop/savealife/app.py
with:
from os import getenv
from chalice import Chalice
try:
from dotenv import load_dotenv
load_dotenv()
except ImportError:
pass
first_name = getenv("WORKSHOP_NAME", "ivica") # replace with your own name of course
app = Chalice(app_name=f"{first_name}-savealife")
@app.route("/donor/signup", methods=["POST"])
def donor_signup():
pass
The most interesting line is highlighted. With it we configure two important parameters of our API:
"/donor/signup"
we’re telling the API Gateway that the route for our Lambda function is /donor/signup
methods=["POST"]
we specify that this route should only react to a POST
requestVerifying that locally shows that we were successful - only POST
requests are accepted:
http -b :8000/donor/signup
Output should be similar to:
http -b POST :8000/donor/signup
But the POST
request will work (even though the endpoint returns null
- it does not error):
When it comes to the JSON payload itself I would propose we keep things simple. What we need from potential donors are 4 pieces of information: their first name, an email for contact, their blood type and the city where they live. So, something like this:
For now our Lambda function does nothing. Let’s make it accept the JSON payload sent to it and simply return it to the caller.
from os import getenv
from chalice import Chalice
try:
from dotenv import load_dotenv
load_dotenv()
except ImportError:
pass
first_name = getenv("WORKSHOP_NAME", "ivica") # replace with your own name of course
app = Chalice(app_name=f"{first_name}-savealife")
@app.route("/donor/signup", methods=["POST"])
def donor_signup():
body = app.current_request.json_body
return body
Chalice comes with a handy helper function for extracting the JSON body of the event sent from the API Gateway - app.current_request.json_body
.
Next to the JSON body, it contains other useful information such as the path that was invoked, headers, the HTTP method used and others.
For the curious, Chalice Request class.
Invoking our function locally with the JSON payload from above results in:
http -b POST :8000/donor/signup first_name=ivica email="ivica@server.com" city=Amsterdam type=A+
Output should be similar to:
If it does, go ahead and deploy it with chalice deploy
and make sure it works when running on AWS.
http -b POST $(chalice url)/donor/signup first_name=ivica email="ivica@server.com" city=Amsterdam type=A+
Output should be the same as when we invoked the function locally:
If it does not work for you now is the time to fix it because the follow-up pages will assume that all the code examples up to now were working.
The JSON payload is not checked against a model/schema - we can send anything we like:
http -b POST $(chalice url)/donor/signup whoami=meow
Output should be similar to: