How To Work with AWS Lambda in Swift

Introducing Swift-Sprinter, an open-source library for Swift with AWS Serverless
Andrea Scuderi - 9/30/19

Introduction

This story starts some years ago when, as an iOS developer at BJSS, I was involved in delivering an iOS mobile app for a government agency in the UK with an AWS Serverless backend. I had an exciting time learning about Lambda, S3, DynamoDB, SNS, Cognito, API Gateway, IAM, and friends. At the end my proof of concept of for an AWS Serverless backend and the mobile iOS Swift native app went to alpha, beta, and now production.

I realised that building this backend for a mobile app with Serverless is inexpensive and scalable from day one and requires very little maintenance compared to a containerised solution or virtual machines. The Serverless approach is quite effective when the backend load cannot be predicted.

The pay per use model introduced with Serverless could be useful in validating a startup idea or a small project.

Only one thing disappointed me — as an iOS developer, I would have written it in my beloved language Swift but at that time it wasn't supported by AWS. So I handed over the PoC of the backend to a developer skilled in the other language and I developed the iOS app.

So I started research in my spare time to make my dream become reality…

A month ago, I came across some half-working solutions that all had a big issue: HTTPS calls were not working.

After I while I developed a working solution with HTTPS and made an open-source framework called swift-sprinter.

With this framework it’s possible to consume AWS services from the Lambda written in Swift 5.0 and 5.1. If you’re curious of how to use swift-sprinter to get an object from an S3 bucket, read this.

The Power of Swift to AWS Lambda

Demo HTTPS API Request from Swift Lambda

To keep the things simple, in this article, I’ll show how to write an AWS Lambda to query the dog-api.

The goal is to retrieve a JSON with a list of images URL from this API by passing our favourite breed:

https://dog.ceo/api/breed/hound/afghan/images

Then retrieving a JSON like this:

{  
    "message": [  
        "https://images.dog.ceo/breeds/hound-afghan/n02088094_1003.jpg",  
        "https://images.dog.ceo/breeds/hound-afghan/n02088094_1007.jpg"  
    ],  
    "status": "success"  
}

You need:

I suggest taking a look at the README on GitHub before you continue the reading to prepare your mac with the requirements.


Development Workflow

From the command line:

git clone https://github.com/swift-sprinter/aws-lambda-swift-sprinter.git
cd aws-lambda-swift-sprinter/Examples/HTTPSRequest

Generate the Xcode project and open it with Xcode:

swift package generate-xcodeproj

Open XCode and Navigate to the file main.swift and inspect it.

The Event is correct — we want to send a URL as an input event.

struct Event: Codable {  
    let url: String  
}

The HTTPSRequest lambda example will give a Response with url and content when the execution is complete — this is not good for our purposes:

struct Response: Codable {  
   let url: String  
   let content: String  
}

We change the response to reflect the JSON we want to receive:

struct Response: Codable {  
   let message: [String]  
   let status: String  
}

We now receive message with an Array of String and a status with a String.

Now to return the Response we need fix the lambda code return type with the new one:

     ... 
    let decoder = JSONDecoder()  
    let output = try decoder.decode(Response.self, from: data)  
    return output  
}

The previous code encodes the data received to Response and returns it as Lambda output.

This is the final output:

main.swift

Now open aws-lambda-swift-sprinter/Makefile

cd ../../ && open Makefile

Comment the following lines:

# HelloWorld Example Configuration  
# SWIFT_EXECUTABLE=HelloWorld  
# SWIFT_PROJECT_PATH=Examples/HelloWorld  
# LAMBDA_FUNCTION_NAME=HelloWorld  
# LAMBDA_HANDLER=$(SWIFT_EXECUTABLE).helloWorld

Then un-comment the line after:

# HTTPSRequest Example Configuration  
SWIFT_EXECUTABLE=HTTPSRequest  
SWIFT_PROJECT_PATH=Examples/HTTPSRequest  
LAMBDA_FUNCTION_NAME=HTTPSRequest  
LAMBDA_HANDLER=$(SWIFT_EXECUTABLE).getHttps
Makefile

Save and close the file.


Lambda Building

Lambda runs on a custom version of Amazon Linux. To build Lambdayou need a Swift custom docker image.

To build the image use this command:

make docker_build

Now test the build from the command line:

make build_lambda

This will take a few minutes.

make build_lambda

Great! The code works on Swift docker too, that means it’s ready to be deployed.


AWS Deployment

To complete this step you must have the AWS Command Line interface installed and have registered your configuration and credentials.

Now we need to build the custom runtime:

make package_layer

We have to upload the lambda layer:

make upload_lambda_layer

Under the .build folder, list a zip file called swift-lambda-runtime-5.1.zip and a file called nio-swift-lambda-runtime-5-1-arn.txt.

make create_lambda

This command will create the Lambda on AWS after rebuilding the code.

After the command complete, go to the AWS console and inspect the HTTPSRequest lambda.


Lambda Invocation

To invoke the Lambda we need to set up the event:

open Examples/HTTPSRequest/event.json

Ùpdate it with this:

{"url": "https://dog.ceo/api/breed/hound/afghan/images"}

Now run the Lambda invocation:

make invoke_lambda
make invoke_lambda

Conclusion

Working with Swift on AWS is becoming a reality, even if at this early stage the solution seems quite promising. If you are interested to get involved in the open-source development of Swift Sprinter the project is open for contributions.

I hope you liked it! Thanks for reading.


References

swift-sprinter/aws-lambda-swift-sprinter

The goal of this project is to provide an environment to build an AWS Lambda Custom Runtime for the Swift programming…


Agile Development for Serverless Platforms

I am still amazed by how much less code you need to create a new serverless application, using technologies such as AWS…


Serverless Computing - Amazon Web Services

Build and run applications without thinking about servers Serverless is the native architecture of the cloud that…


Serverless Computing with Swift

Part 1: Swift and AWS Lambda

Tagged with: Swift Lambda APIGateway