Status: Beta

This Builder takes in a Rust program and outputs it as a Lambda.

When to Use It

Whenever you want to expose an API or a function written in Rust.

How to Use It

Define an index.rs file inside a folder as follows:

use http::{Request, Response, StatusCode, header};

fn handler(request: Request<()>) -> http::Result<Response<String>> {
    let response = Response::builder()
        .status(StatusCode::OK)
        .header(header::CONTENT_TYPE, "text/html")
        .body("<!doctype html><html><head><title>A simple deployment with Now!</title></head><body><h1>Welcome to Rust on Now</h1></body></html>".to_string())
        .expect("failed to render response");

    Ok(response)
}

Define a Cargo.toml like so:

[package]
name = "rust-project"
version = "0.1.0"
edition = "2018"

[dependencies]
http = "0.1"

A Cargo.toml file defining the Rust dependencies.

Note: Your Cargo.toml file should contain the Rust crates used in your application.

And define a now.json like:

{
  "name": "rust-project",
  "version": 2,
  "builds": [
    {
      "src": "index.rs",
      "use": "@now/rust"
    }
  ]
}

A now.json file defining the Now platform version and a build step using the @now/rust Builder.

The example above can be seen live at https://rust-kit-rm1x19uq8.now.sh/.

Also, the source code of the deployment can be checked by appending /_src e.g. https://rust-kit-rm1x19uq8.now.sh/_src.

Development

The now dev command allows you to develop lambdas locally on your machine. With now dev and @now/rust you can develop your rust-based lamdas on your own machine.

During local development with now dev, the assumption is that rust and cargo are already installed and available in your PATH since they will not be installed automatically. The recommended way to install rust and cargo on your machine is with rustup.

Technical Details

Entry Point

The entry point file can either be a .rs source file or a Cargo.toml file.

.rs Entry Point

When you use one or multiple .rs files as an entry point for this Builder, Now will setup the serverless environment for you.

The requirements for this entry point is to expose a handler function and not to have a main function.

The example for the "How to Use It" section uses this method.

If a Cargo.toml exists in the project relating to the entry point, the dependencies will be installed for the Rust project.

Cargo.toml Entry Point

When using a Cargo.toml file as an entry point for this Builder, Now will use cargo read-manifest to build each binary within the project. It means that cargo workspaces are not supported as an entry point for now. See cargo workspace workaround

This entry point method is an advanced method of using this Builder and requires Rust files to assemble their own runtimes.

Defining a Cargo.toml file as an entry point requires a Rust file at src/main.rs or files defined as a [[bin]]` target.

An example src/main.rs Rust file within a project including a Cargo.toml file acting as the entry point:

use http::{StatusCode, header};
use now_lambda::{error::NowError, lambda, IntoResponse, Request, Response};
use std::error::Error;

fn handler(request: Request) -> Result<impl IntoResponse, NowError> {
    let uri = request.uri();
    let response = Response::builder()
        .status(StatusCode::OK)
        .header(header::CONTENT_TYPE, "text/html")
        .body(format!(
            "You made a request to the following URL: {}",
            uri
        ))
        .expect("failed to render response");

    Ok(response)
}

// Start the runtime with the handler
fn main() -> Result<(), Box<dyn Error>> {
    Ok(lambda!(handler))
}

This requires one dependency, with the example above using another dependency, http.

The required dependency is now_lambda which provides all of the resources needed to provide the serverless runtime.

The Cargo.toml entry point for the example above is the following:

[package]
name = "rust-project"
version = "0.1.0"
edition = "2018"

[dependencies]
http = "0.1"
now_lambda = "*"

An example Cargo.toml entry point defining http and now_lambda dependencies.

Dependencies

This Builder supports installing dependencies defined in the Cargo.toml file.

Furthermore, more system dependencies can be installed at build time with the presence of a shell build.sh file in the same directory as the entry point file.

By default, openssl is installed by the Builder due to its common usage with Rust projects.

Rust Version

This builder uses rustup to install rust and cargo. By default, the latest stable version of rust will be installed. To see what the current stable version of rust is, please see the official website.

If you need to use a different version of rust other than the latest stable version, you can specify a version of rust in your build's configuration. Accepted values are the same as rustup's channel definition, which is stable | latest | nightly | <version>.

Example rust version configuration:
{
  "builds": [
    { "src": "Cargo.toml", "use": "@now/rust", "config": { "rust": "1.35" } }
  ]
}

Maximum Lambda Bundle Size

To help keep cold boot times low, the maximum output bundle size for a Rust lambda is, by default, 25mb. This limit is extendable up to 50mb.

Example maxLambdaSize configuration:
{
  "builds": [
    { "src": "*.rs", "use": "@now/rust", "config": { "maxLambdaSize": "40mb" } }
  ]
}

Resources

The goal of the ZEIT Docs is to provide you with all the information you need to easily deploy your projects. The following resources can also help you set up other projects:

Cargo Workspaces Workaround

Cargo's workspaces feature is a great tool when working on multiple binaries and libraries in a single project. If a cargo workspace is found in the entrypoint, however, @now/rust will fail to build.

To get around this limitation, create build entries in your now.json file for each Cargo.toml that represents a lambda function within your workspace. In your .nowignore, you'll want to add any binary or library project folders that aren't needed for your lambdas to speed up the build process like your Cargo.toml workspace.

It's also recommended to have a Cargo.lock alongside your lambda Cargo.toml files to speed up the build process. You can do this by running cargo check or a similar command within each project folder that contains a lambda.

If you have a compelling case for workspaces to be supported by @now/rust which are too cumbersome with this workaround, please contact us! We're always looking for feedback.