I am new to the serverless web development world (after spending a few years in the aws sysops/devops world). This todo app is just a learner app to get me comfortable building rest apis with lambda functions. I appreciate any help. Thanks!
Below is 1. The code, 2. The requests send via POSTMAN, 3. The Cloudwatch logs
1. The relevant code snippets.
Ask for missing context in comments if I missed something.
# models.py
from pynamodb.models import Model
from pynamodb.attributes import UnicodeAttribute, BooleanAttribute
class TodoItem(Model):
class Meta:
table_name = 'todo_items'
region = 'eu-central-1'
item_id = UnicodeAttribute(hash_key=True)
item_name = UnicodeAttribute()
item_status = BooleanAttribute(default=False)
# app.py
from aws_lambda_powertools import Logger
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from models import TodoItem
import uuid
logger = Logger()
app = APIGatewayRestResolver()
@app.get('/todo/{item_id}')
def get_todo_item(item_id):
logger.info(f'get_todo_item: {item_id}')
item = TodoItem.get(item_id)
return item.attribute_values
@app.post('/todo')
def create_todo_item():
logger.info('create_todo_item')
item_data = app.current_event.json_body
logger.info(f"item_name: {item_data['item_name']}")
item = TodoItem(item_id=str(uuid.uuid4()), item_name=item_data['item_name'])
item.save()
return item.attribute_values
def lambda_handler(event, context):
logger.info(f'event: {event}')
return app.resolve(event, context)
2. The following two requests were made with POSTMAN.
POST Request to https://lambdaprefix.execute-api.eu-central-1.amazonaws.com/Prod/todo/
POST Response: {"item_status":false,"item_id":"c36bfc42-e8fd-4bd0-b246-bb99be9c5487","item_name":"test-todo-item-name yolo"}
I have checked and confirmed that the data was saved to the dynamodb table.
GET Request to https://lambdaprefix.execute-api.eu-central-1.amazonaws.com/Prod/todo/c36bfc42-e8fd-4bd0-b246-bb99be9c5487
GET Response: {"statusCode":404,"message":"Not found"}
The request returns a 404 when requesting with the exact item_id returned by the POST response / saved in the DB
3. The logs
LOG1:
Code:
def lambda_handler(event, context):
logger.info(f'event: {event}')
return app.resolve(event, context)
Log:
{
"level": "INFO",
"location": "lambda_handler:53",
"message": "event: {'resource': '/todo/{id}', 'path': '/todo/c36bfc42-e8fd-4bd0-b246-bb99be9c5487', 'httpMethod': 'GET', 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate, br', 'CloudFront-Forwarded-Proto': 'https', 'CloudFront-Is-Desktop-Viewer': 'true', 'CloudFront-Is-Mobile-Viewer': 'false', 'CloudFront-Is-SmartTV-Viewer': 'false', 'CloudFront-Is-Tablet-Viewer': 'false', 'CloudFront-Viewer-ASN': '9009', 'CloudFront-Viewer-Country': 'AT', 'Host': 'lambdaprefix.execute-api.eu-central-1.amazonaws.com', 'Postman-Token': 'ef43b28b-eb20-4feb-9503-9c3ca4ae3b5c', 'User-Agent': 'PostmanRuntime/7.32.2', 'Via': '1.1 e77ae8cfd42b65dd9027fa08596c6f2a.cloudfront.net (CloudFront)', 'X-Amz-Cf-Id': 'DRtAi5i4sBEkeK4xZDPy_S_5bbBfi9J7dACytDCIRK9oi00IDchRbQ==', 'X-Amzn-Trace-Id': 'Root=1-6495c1af-505c7a9f36e4b0d6011af833', 'X-Forwarded-For': '146.70.116.141, 130.176.38.185', 'X-Forwarded-Port': '443', 'X-Forwarded-Proto': 'https'}, 'multiValueHeaders': {'Accept': ['*/*'], 'Accept-Encoding': ['gzip, deflate, br'], 'CloudFront-Forwarded-Proto': ['https'], 'CloudFront-Is-Desktop-Viewer': ['true'], 'CloudFront-Is-Mobile-Viewer': ['false'], 'CloudFront-Is-SmartTV-Viewer': ['false'], 'CloudFront-Is-Tablet-Viewer': ['false'], 'CloudFront-Viewer-ASN': ['9009'], 'CloudFront-Viewer-Country': ['AT'], 'Host': ['lambdaprefix.execute-api.eu-central-1.amazonaws.com'], 'Postman-Token': ['ef43b28b-eb20-4feb-9503-9c3ca4ae3b5c'], 'User-Agent': ['PostmanRuntime/7.32.2'], 'Via': ['1.1 e77ae8cfd42b65dd9027fa08596c6f2a.cloudfront.net (CloudFront)'], 'X-Amz-Cf-Id': ['DRtAi5i4sBEkeK4xZDPy_S_5bbBfi9J7dACytDCIRK9oi00IDchRbQ=='], 'X-Amzn-Trace-Id': ['Root=1-6495c1af-505c7a9f36e4b0d6011af833'], 'X-Forwarded-For': ['146.70.116.141, 130.176.38.185'], 'X-Forwarded-Port': ['443'], 'X-Forwarded-Proto': ['https']}, 'queryStringParameters': None, 'multiValueQueryStringParameters': None, 'pathParameters': {'id': 'c36bfc42-e8fd-4bd0-b246-bb99be9c5487'}, 'stageVariables': None, 'requestContext': {'resourceId': 'p8pwqo', 'resourcePath': '/todo/{id}', 'httpMethod': 'GET', 'extendedRequestId': 'G-szfGo6FiAFsAw=', 'requestTime': '23/Jun/2023:16:00:47 +0000', 'path': '/Prod/todo/c36bfc42-e8fd-4bd0-b246-bb99be9c5487', 'accountId': '216411484155', 'protocol': 'HTTP/1.1', 'stage': 'Prod', 'domainPrefix': 'lambdaprefix', 'requestTimeEpoch': 1687536047656, 'requestId': '33bafab2-0823-405c-819b-16bdb84bd773', 'identity': {'cognitoIdentityPoolId': None, 'accountId': None, 'cognitoIdentityId': None, 'caller': None, 'sourceIp': '146.70.116.141', 'principalOrgId': None, 'accessKey': None, 'cognitoAuthenticationType': None, 'cognitoAuthenticationProvider': None, 'userArn': None, 'userAgent': 'PostmanRuntime/7.32.2', 'user': None}, 'domainName': 'lambdaprefix.execute-api.eu-central-1.amazonaws.com', 'apiId': 'lambdaprefix'}, 'body': None, 'isBase64Encoded': False}",
"timestamp": "2023-06-23 16:00:48,540+0000",
"service": "service_undefined",
"xray_trace_id": "1-6495c1af-505c7a9f36e4b0d6011af833"
}
LOG2:
Code:
@app.get('/todo/{item_id}')
def get_todo_item(item_id):
logger.info(f'get_todo_item: {item_id}')
item = TodoItem.get(item_id)
return item.attribute_values
Logs:
NOTHING! The function doesn't ever get called even though the event data logged previously shows this:
event: {'resource': '/todo/{id}', 'path': '/todo/c36bfc42-e8fd-4bd0-b246-bb99be9c5487', 'httpMethod': 'GET',