Bash Builder (@now/bash)

The @now/bash Builder takes an entrypoint of a bash function, imports its dependencies, and bundles them into a Lambda.

A simple "hello world" example:

handler() {
  echo "Hello, from Bash!"
}

This Builder is the recommended way to build lambdas from shell functions.

This example will detail creating an uppercase endpoint which will be accessed as my-deployment.url/api/uppercase. This endpoint will convert the provided querystring to uppercase using only Bash functions and standard Unix CLI tools.

Start by creating the project structure:

mkdir -p my-bash-project/api/uppercasecd my-bash-project/api/uppercase

Inside the my-bash-project > api > uppercase directory, create an index.sh file with the following contents:

import "string@0.0.1"
import "querystring@1.3.0"

handler() {
  local path
  local query
  path="$(jq -r '.path' < "$REQUEST")"
  querystring "$path" | querystring_unescape | string_upper
}

A shell function that takes querystrings and prints them as uppercase.

The final step is to define a build that will take this entrypoint (index.sh), build it, and turn it into a lambda using a now.json configuration in the root directory (my-bash-project):

{
  "version": 2,
  "builds": [{ "src": "api/**/index.sh", "use": "@now/bash" }]
}

A now.json file using a build which takes a shell file and uses the @now/bash Builder to output a lambda.

The resulting deployment can be seen here: https://bash-o54wu79wa.now.sh/

Note, however, that it will return an empty response without a querystring.

By passing in a querystring, the lambda will return the uppercased version. For example: https://bash-o54wu79wa.now.sh/api/uppercase?hello%20world

The entrypoint of this Builder is a shell file that defines a handler() function. The handler() function is invoked for every HTTP request that the Lambda receives.

If your Lambda requires additional resources to be added into the final bundle, an optional build() function may be defined.

Any files added to the current working directory at build-time will be included in the output Lambda.

build() {
  date > build-time.txt
}

handler() {
  echo "Build time:   $(cat build-time.txt)"
  echo "Current time: $(date)"
}

Demo: https://bash-build-j3adniz41.now.sh/

Bash, by itself, is not very useful for writing Lambda handler logic because it does not have a standard library. For this reason, import is installed and configured by default, which allows your script to easily include additional functionality and helper logic.

For example, the querystring import may be used to parse input parameters from the request URL:

import "querystring@1.3.0"

handler() {
  local path
  local query
  path="$(jq -r '.path' < "$REQUEST")"
  query="$(querystring "$path")"
  echo "Querystring is: $query"
}

Demo: https://bash-querystring-fommsvjvs.now.sh/?a=b

With the @now/bash Builder, the handler script is executed using GNU Bash 4.

handler() {
  bash --version
}

Demo: https://bash-version-rkb5w4ua6.now.sh/

To help keep cold boot times minimal, the default maximum output bundle size for a Bash lambda function is 10mb. This limit is extendable up to 50mb.

Example maxLambdaSize configuration:
{
  "builds": [
    { "src": "*.sh", "use": "@now/bash", "config": { "maxLambdaSize": "20mb" } }
  ]
}