- Published on
Create your own QR Code Generator with AWS and AWS CDK! - Deploying your website and connecting it with your API
- Authors
- Name
- Katherine Moreno
Introduction
This post continues our journey left from our previous blog
In this one we will deploy our website by using S3 and Cloudfront, if you want to know how you can visit my other post
And also we will know how to allow to call to our API from our website by using CORS.
The architecture
How I did it
Our Stack should now be including the definition of S3 with Cloudfront.
from aws_cdk import (
CfnOutput,
Stack,
aws_lambda as lambda_,
aws_apigateway as apigateway,
aws_s3 as s3,
aws_s3_deployment as s3deploy,
)
from aws_cdk.aws_cloudfront import BehaviorOptions, Distribution, OriginAccessIdentity
from aws_cdk.aws_cloudfront_origins import S3Origin
from aws_cdk.aws_lambda_python_alpha import (
PythonFunction,
)
from constructs import Construct
import os
class QrGeneratorStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
# -------------- Frontend ------------------#
# Create a bucket to host the website
qr_website_bucket = s3.Bucket(
self, "qr_website_bucket", access_control=s3.BucketAccessControl.PRIVATE
)
# Verify if the folder exists
website_dir = os.path.join(os.path.dirname(__file__), "website")
if not os.path.isdir(website_dir):
raise FileNotFoundError(f"El directorio {website_dir} no existe")
qr_origin_access_identity = OriginAccessIdentity(self, "OriginAccessIdentity")
qr_website_bucket.grant_read(qr_origin_access_identity)
qr_distribution = Distribution(
self,
"Distribution",
default_root_object="website.html",
default_behavior=BehaviorOptions(
origin=S3Origin(
qr_website_bucket, origin_access_identity=qr_origin_access_identity
)
),
)
s3deploy.BucketDeployment(
self,
"DeployWebsite",
sources=[s3deploy.Source.asset(website_dir)],
destination_bucket=qr_website_bucket,
distribution=qr_distribution,
distribution_paths=["/*"], # This is for invalidation of the cache
)
# This makes to print in the console log the domain of the distribution
CfnOutput(self, "DomainName", value=qr_distribution.domain_name)
# ------------------------ Backend -------------------------------------#
# Create the s3 Bucket
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,
)
cf_domain_name = "https://" + qr_distribution.domain_name
# 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,
"ALLOWED_ORIGIN": cf_domain_name,
},
description="Lambda for creating the QR code",
)
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")
#Adding Cors
qr.add_cors_preflight(
allow_methods=["POST", "OPTIONS"],
allow_origins=[cf_domain_name],
)
qr.add_method("POST", qr_code_integration)
Now Pay attention to this part, this is what we will allow us to enable CORS to the API Gateway level
qr.add_cors_preflight(
allow_methods=["POST", "OPTIONS"],
allow_origins=[cf_domain_name],
)
Also at the level of our lambda we need to update our lambda to be more restrictive and only allow requests from a browser only if the browser is the one that we've defined on the "Access-Control-Allow-Origin" field.
...
return {
...
"headers": {
"Access-Control-Allow-Headers": "Content-Type",
"Access-Control-Allow-Origin": os.environ["ALLOWED_ORIGIN"],
"Access-Control-Allow-Methods": "OPTIONS,POST",
},
}
Epilogue
We've deployed a website which interacts with our backends and allow to users to generate QR Codes.