This project is aimed to demonstrate how to implement a Serverless Functions working with WebAssembly in AWS Lambda, using our WasmEdge runtime. Docker is also required for this demo.
The main branch showcases an image processing function, and the tensorflow branch showcases an AI inference function. Both written in simple Rust and runs in the WasmEdge runtime for WebAssembly.
The Serverless Functions endpoint is located at api/hello.js to meet the requirement of AWS Lambda. AWS Lambda requires a function handler as the entry point for various events.
The only function in api/hello.js is grayscale
, which transforms a colored image into a grayscale image. It receives a PNG file and pass it as STDIN stream to a spawned child process. The child process runs using the WasmEdge command.
File api/functions/image-grayscale/src/main.rs
implements the grayscaling logic. You can build it with the Rust cargo
command with the -target wasm32-wasi
option to get the grayscale.wasm file.
We define custom build in api/pre.sh which is called in package.json to download the WasmEdge command.
Go to your Amazon Elastic Container Registry (ECR) and create a new image repository. Note that you need to set the visibility settings to Private in order to use the image to create a serverless function on AWS Lambda.
We have everything we need to build a docker image in the api/ folder.
-
grayscale.wasm is the WebAssembly function that turns a colored picture into black and white. grayscale.wasm is compiled from main.rs in api/functions/image-grayscale/src, written in Rust.
-
hello.js is the handler function that passes data of the HTTP request to the grayscale function and runs it. This is required by AWS Lambda.
-
pre.sh is the shell script that installs the WasmEdge runtime and all its dependencies. pre.sh is executed while building the Docker image.
To build the image, make sure the Dockerfile we provided is in the api/ folder and run
$ cd api
$ docker build -t aws_lambda_grayscale .
You can follow the instructions provided by your ECR repository to push the image. Note that AWS CLI is required in this step.
Now go to AWS Lambda Console and create a new serverless function. Choose to create a function from container image. Put in the name of your function and your container image URL. You can browse images from your private repositories on Amazon ECR or simply paste the container image URL.
After creating your function, we need to set up a trigger for your function. A trigger simply defines how your function is called. In this demo we want to call our function through HTTP request, so we will create an API as the trigger.
Click Add trigger.
Choose API Gateway as trigger type. For API type, choose REST API. For Security, choose Open.
Once we have created our API, we see that an API endpoint is now available. This is the URL we can use to call our serverless function.
Finally, if we want to call our function within a browser, we need to enable CORS. To do so, we need to click the linked text grayscale-API next to API Gateway to enter the Amazon API Gateway console.
In the API Gateway console, click Actions and choose Enable CORS.
Default options should be enough for our demo.
If you find that your serverless function always returns internal server error
, if might be due to that the default timeout interval is too short for our function to execute. The default timeout interval is 3 seconds for any AWS Lambda function. You may increase the timeout interval to give enough time for the serverless function to execute. Setting Timeout to 30 seconds should be more than enough.
This demo provides a simple front-end UI made by Next.js. It is a static web page deployed through GitHub pages. To set up this static page, all you need to do is add your serverless function endpoint URL to Secrets in the Settings page under the name NEXT_PUBLIC_FUNCTION_URL
, as shown below.
We use GitHub Actions to generate pages, so the workflow in .github/workflows/deploy.yml (which builds the front-end page) is triggered every time you commit your changes.
Caveats:
-
If you have forked this repository and wish to enable this auto-build feature, you need to manually allow actions to run under the Actions tab in Settings, since by default GitHub Actions are not trigger in forked repositories.
-
If you are building the
gh-pages
branch for the first time, please add an empty file with the name.nojekyll
ingh-pages
after the branch is built. Doing so prevents some of your web resources from being ignored by GitHub while presenting your page.
grayscale.wasm is built with cargo
as follows:
$ cd api/functions/image-grayscale/
$ cargo build --release --target wasm32-wasi
$ cp target/wasm32-wasi/release/grayscale.wasm ../../
You can write your own Rust code and build your own WebAssembly function in a similar way. Don't forget to specify how your function should be called in api/hello.js. Follow the same steps in this demo to deploy your function to AWS Lambda.
Congrats! You have created your own serverless function!
To learn more about WasmEdge, take a look at the following resources:
- WasmEdge's Github repo
- WasmEdge Tutorials
- Check out Second State's repositories for more demos, as well as resources on Rust and Wasm