DEV Community

Cover image for Deploying a REST API and Angular Frontend Using AWS CDK, S3, and API Gateway
Kevin Lactio Kemta
Kevin Lactio Kemta

Posted on • Updated on

Deploying a REST API and Angular Frontend Using AWS CDK, S3, and API Gateway

Day 008 - 100DaysAWSIaCDevopsChallenge

I recently, on day 007 of my 100 Days of Code challenge, created an infrastructure to deploy a REST API beyand and Api Gateway. Today I am going to create an angular application that will consume the API exposed by API Gateway. The Angular application will be built and deployed in an S3 Bucket as a static website.

To achieve this, we will follow the steps below:

  • Set up the Angular app: Create or clone the Angular app in a github repository.
  • Create and configure the S3 Bucket to hosting website: Set up the S3 Bucket as static website.
  • Build angular deployable files: Build the Angular application.
  • Upload the bundle files to the S3 Bucket.
Prerequises
  • AWS Cloud Developement Kit (CDK)
  • S3 Bucket, IAM
  • Typescript, Angular

Infrastructure Diagram

Image description

Build Angular App

This Angular application provides functionality to create and manage to-do lists. Users can add new tasks, view existing tasks. The app leverages Angular's powerful capabilities for efficient data binding and component-based architecture, ensuring a seamless user experience.

You can explore the complete source code and documentation in my Github repository ↗

npm install -g @angular/cli
git clone https://github.com/nivekalara237/100DaysTerraformAWSDevops.git
cd 100DaysTerraformAWSDevops/apps/todo-app
npm install
ng serve
Enter fullscreen mode Exit fullscreen mode

Create and configure the S3 Bucket to hosting website

import { aws_iam as iam, aws_s3 as s3, Duration, RemovalPolicy, Stack, StackProps } from 'aws-cdk-lib'
import { Construct } from 'constructs'
import { HttpMethods } from 'aws-cdk-lib/aws-s3'

export interface WebsiteStackProps extends StackProps {
  bucketName: string
}

export class WebsiteStack extends Stack {
  constructor(scope: Construct, id: string, props: WebsiteStackProps) {
    super(scope, id, props)

    const wsBucket = new s3.Bucket(this, 'WebsiteBucketResource', {
      bucketName: props.bucketName,
      removalPolicy: RemovalPolicy.DESTROY,
      autoDeleteObjects: true,
      versioned: true,
      eventBridgeEnabled: false,
      websiteIndexDocument: 'index.csr.html',
      websiteErrorDocument: 'index.csr.html',
      blockPublicAccess: s3.BlockPublicAccess.BLOCK_ACLS
    })
    wsBucket.grantRead(new iam.StarPrincipal(), '*')
    wsBucket.addCorsRule({
      allowedMethods: [
        s3.HttpMethods.GET,
        HttpMethods.HEAD, HttpMethods.DELETE,
        HttpMethods.PUT, HttpMethods.POST
      ],
      allowedOrigins: ['*'],
      maxAge: Duration.minutes(30).toSeconds()
    })
  }
}
//stacks/website-stack.ts
Enter fullscreen mode Exit fullscreen mode
  • websiteIndexDocument: a file that should be served as the home page of your website. It specifies the name of the index file (in our case index.csr.html) that S3 should serve when a user requests the root URL of your website or any subdirectory.
  • websiteErrorDocument: It specifies the error page to display when a user encounters an error, such as a 404 Not Found error, while accessing your static website hosted on S3. In our case, we need to redirect all errors to the index file. This is necessary to avoid S3’s default 404 Object Not Found error and to allow Angular to handle routing on its own.
wsBucket.grantRead(new iam.StarPrincipal(), '*')
Enter fullscreen mode Exit fullscreen mode

Allow public read in our Bucket, this line will generate role permission below:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetBucket*",
                "s3:GetObject*",
                "s3:List*"
            ],
            "Resource": [
                "arn:aws:s3:::bucket/<BUCKET_NAME>",
                "arn:aws:s3:::bucket/<BUCKET_NAME>/*"
            ],
            "Principal": "*"
        }
    ]
}
Enter fullscreen mode Exit fullscreen mode

Then, add a cross-origin access configuration to the Amazon S3 bucket by:

wsBucket.addCorsRule({...})
Enter fullscreen mode Exit fullscreen mode

Deploy the entire infrastructure

cd 100DaysTerraformAWSDevops/day_008
cdk deploy --profile cdk-user --all
Enter fullscreen mode Exit fullscreen mode

It will deploy three stacks Day008CdkStack, Day008WebsiteBucketStack and Day008LambdaLayerStack.

Build angular deployable files

cd 100DaysTerraformAWSDevops/apps/todo-app
ng build --configuration production
Enter fullscreen mode Exit fullscreen mode

The output is located in the dist/todo-app/browser directory.

Upload the bundle files to the S3 Bucket

To upload the bundle files generated previously, we have two options:

Upload files using AWS CLI

To upload files to s3 Bucket we need to install aws cli [↗] and configure it [↗]
Open the terminal at project root and run the following commands:

aws s3 cp dist/todo-app/browser s3://${BUCKET_NAME}/ --recursive
Enter fullscreen mode Exit fullscreen mode

Rename BUCKET_NAME with the name of your S3 bucket

Upload files using Console
  1. Open the S3 console [↗].
  2. Select the bucket BUCKET_NAME.
  3. Click on the Upload button.
  4. Add the files or/and folder you want to upload.
  5. Configure additional settings if required.
  6. Start the upload process.
  7. Monitor the upload progress in the console.
  8. Once the upload is complete, the files will be available in the bucket.

S3 Console

The application is deployed and accessible at:

  • Amazon S3 Console: Go to Amazon S3 -> Bucket -> BUCKET_NAME -> Properties tab -> Static website hosting.
  • Direct URL: You can also access it directly via http://<BUCKET-NAME>.s3-website-<REGION>.amazonaws.com.

🥳✨
We have reached the end of the article.
Thank you so much 🙂


Your can find the full source code on GitHub Repo

Top comments (0)