- Published on
Create your own QR Code Generator with AWS and AWS CDK! - Creating The API
- Authors
- Name
- Katherine Moreno
Introduction
In my efforts trying to keep challenguing myself in my journey to improve my AWS skills I found the challengue from Rishab Kumar to setup a QR Code generator. On his video, Rishab give us the architecture to start the project.
I decided to give it a bit Twist and instead of using Function Lambda URLs, expose the Lambda through API Gateway.
How I did it
To generate the qr code we use the qrcode library and to generate unique filenames of the objects we use the uuid library.
# This lambda receives the URL as parameter
import boto3
import json
import qrcode
import uuid
import io
import os
s3 = boto3.client("s3")
region = os.environ["REGION"]
bucket_name = os.environ["BUCKET_NAME"]
def handler(event, context):
randomUuid = str(uuid.uuid4)
body = event["body"]
parsed_body = json.loads(body)
url = parsed_body["url"]
# Generate QR code
img = qrcode.make(url)
img_bytes = io.BytesIO()
img.save(img_bytes)
img_bytes = img_bytes.getvalue()
# Generate a unique filename
filename = randomUuid + ".png"
# Upload the object to S3
s3.put_object(
Body=img_bytes,
Bucket=bucket_name,
Key=filename,
ContentType="image/png",
ACL="public-read",
)
url_code = f"https://{bucket_name}.s3.{region}.amazonaws.com/{filename}"
return {
"statusCode": 200,
"body": json.dumps(
{
"message": "QR code generated and uploaded to S3 bucket successfully!",
"qr_code_url": url_code,
}
),
"headers": {
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "*",
},
}
As we are using as external dependency the library qrcode we need to define a requirements.txt. More information about how to bundle external dependencies here.
qrcode==7.4.2
and in our Stack API
from aws_cdk import (
Stack,
aws_lambda as lambda_,
aws_apigateway as apigateway,
aws_s3 as s3,
)
from aws_cdk.aws_lambda_python_alpha import (
PythonFunction,
)
from constructs import Construct
class QrGeneratorStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# ------------------------ Backend -------------------------------------#
# Create the S3 Bucket with ACL Configuration
bucket = s3.Bucket(
self,
"Bucket",
block_public_access=s3.BlockPublicAccess(
block_public_acls=False,
block_public_policy=False,
ignore_public_acls=False,
restrict_public_buckets=False,
),
object_ownership=s3.ObjectOwnership.OBJECT_WRITER,
)
# Create the lambda
create_qr_lambda = PythonFunction(
self,
"CreateQrCodeLambda",
function_name="createQrCodeLambda",
runtime=lambda_.Runtime.PYTHON_3_11,
index="create_qr.py", # Path to the directory with the Lambda function code
handler="handler", # Handler of the Lambda function
entry="./lambda",
environment={
"REGION": self.region,
"BUCKET_NAME": bucket.bucket_name,
},
description="Lambda for creating the QR code",
)
#Grant permissions to the Lambda
bucket.grant_read_write(create_qr_lambda)
bucket.grant_put_acl(create_qr_lambda)
# Define the API Gateway
api = apigateway.RestApi(self, "ApiGatewayQR", rest_api_name="RestAPI QR")
qr_code_integration = apigateway.LambdaIntegration(create_qr_lambda)
qr = api.root.add_resource("qr")
qr.add_method("POST", qr_code_integration)
The most complicated part was to configure the ACL but this thread on Github help me to condigure it. We test it on Postman and Voila! We've our endpoint which returns a url and if we click on the url it give us the image of the Generated QR Code!
Epilogue
We've learn to create an API which generates qr codes, but is not enough. Keep reading in my following post how did I host the website with S3 and Cloudfront