How-tos & Examples

Note

If you try these examples on your computer by copying/pasting the code snippets from this page, be aware that it’ll only work if “mock” is installed as a global executable.

A “Who is” Lookup Service

mock serve -p 3000 \
    --route 'whois' \
    --exec 'whois $(mock get-query domain) | mock write'

Let’s now test it:

$ curl localhost:3000/whois?domain=google.com
# Prints out:
# Domain Name: GOOGLE.COM
# Registry Domain ID: 2138514_DOMAIN_COM-VRSN
# ...

What if the visitor accesses our service without passing a domain querystring? Let’s handle that, showing a HTML page where the visitor can enter a domain name to be looked up:

$ mock serve -p 3000 \
    --route 'whois' \
    --exec '
DOMAIN="$(mock get-query domain)"

if [ -z "${DOMAIN}" ]
then
    mock set-header "Content-Type" "text/html; charset=utf-8"

    mock write <<EOF
<!DOCTYPE html>
<html lang="en">
<body>
    <form action="/whois" method="get">
        Domain:
        <br />
        <input type="text" name="domain" placeholder="Enter a domain" />
        <br />
        <br />
        <input type="submit" value="Go!" />
    </form>
</body>
</html>
EOF

    exit 0
fi

whois ${DOMAIN} | mock write
'

Youtube Downloader Web Service

$ mock serve -p 3000 \
    --route "/download/{video_id}" \
    --exec '
VIDEO_ID="$(mock get-route-param video_id)"

cd $(mktemp -d)

yt-dlp "https://www.youtube.com/watch?v=${VIDEO_ID}" -f 92

FILE_NAME="$(ls | head -n 1)"

mock set-header "Content-Disposition" "attachment; filename=\"${FILE_NAME}\""

mock write < "${FILE_NAME}"
'

Let’s test it: in your browser, open up the following address:

http://localhost:3000/download/jNQXAC9IVRw

An API powered by multiple languages

$ mock serve -p 3000 \
    --route js \
    --exec '
node <<EOF | mock write
console.log("Hello from Node.js!")
EOF
' \
    --route python \
    --exec '
python3 <<EOF | mock write
print("Hello from Python!")
EOF
' \
    --route php \
    --exec '
php <<EOF | mock write
<?php
echo "Hello from PHP!\n";
?>
EOF
'

Let’s test it:

$ curl localhost:3000/js
# Prints out: Hello from Node.js!
$ curl localhost:3000/python
# Prints out: Hello from Python!
$ curl localhost:3000/php
# Prints out: Hello from PHP!

A stateful API

$ export TMP=$(mktemp)
$ printf "0" > "${TMP}"

$ mock serve -p 3000 \
    --route '/hello' \
    --exec '
printf "%s + 1\n" "$(cat ${TMP})" | bc | sponge "${TMP}"

printf "This server has received %s request(s) so far." "$(cat '"${TMP}"')" | mock write
'

Let’s test it:

$ curl localhost:3000/hello
# Prints out: This server has received 1 request(s) so far.
$ curl localhost:3000/hello
# Prints out: This server has received 2 request(s) so far.
$ curl localhost:3000/hello
# Prints out: This server has received 3 request(s) so far.

A CRUD API with a simple data storage

The following API does two tasks: add users and fetch users.

Warning

To run this example, you’ll need to have jq installed, as the “/users” endpoint uses it for parsing.

$ export DATA_DIR=$(mktemp -d)

$ mock serve -p 3000 \
    --route 'user' \
    --method POST \
    --exec '
# Insert a new user

USER_NAME=$(mock get-payload name)
USER_EMAIL=$(mock get-payload email)
NEW_USER_ID="$(ls $DATA_DIR | wc -l | sed "s/$/+1/" | bc)"

printf "New user ID generated: %s\n" "${NEW_USER_ID}"

printf '"'"'{"name":"%s","email":"%s"}'"'"' "${USER_NAME}" "${USER_EMAIL}" > "${DATA_DIR}/${NEW_USER_ID}.json"

printf '"'"'{"id":"%s"}'"'"' "${NEW_USER_ID}" | mock write
' \
    --route 'user/{user_id}' \
    --exec '
# Get an existing user

USER_ID="$(mock get-route-param user_id)"
USER_FILE="${DATA_DIR}/${USER_ID}.json"

if [ ! -f "${USER_FILE}" ]
then
    mock set-status 400

    exit 0
fi

mock write < "${USER_FILE}"
' \
    --route 'users' \
    --exec '
# Gets ALL users

cat $DATA_DIR/*.json | jq -s | mock write
'

Let’s now test it:

$ curl -X POST localhost:3000/user \
    -H 'Content-Type: application/json' \
    -d @- <<EOF
{"name":"John Doe","email":"john.doe@example.com"}
EOF
# Prints out: {"id":"1"}

$ curl -X POST localhost:3000/user \
    -H 'Content-Type: application/json' \
    -d @- <<EOF
{"name":"Jane Doe","email":"jane.doe@example.com"}
EOF
# Prints out: {"id":"2"}

$ curl -v localhost:3000/user/1
# Prints out: {"name":"John Doe","email":"john.doe@example.com"}
$ curl -v localhost:3000/user/2
# Prints out: {"name":"Jane Doe","email":"jane.doe@example.com"}

$ curl -v localhost:3000/user/10
# will fail with 400/BadRequest

$ curl -v localhost:3000/users
# Prints out: [
#  {"name":"John Doe","email":"john.doe@example.com"},
#  {"name":"Jane Doe","email":"jane.doe@example.com"}
# ]

Delaying specific endpoints

Making an existing API slow can be easily accomplished combining mock’s Base APIs and the delay option.

$ mock serve -p 8000 --base example.com --delay 2000

You may want however to make a specific endpoint slow instead of the whole API. This can be achieved using middlewares:

$ mock serve -p 8000 --base example.com --middleware '
if [ "${MOCK_REQUEST_ENDPOINT}" = "some/endpoint" ]
then
    sleep 2 # wait two seconds
fi
'

With that last example, our API at localhost:8000 will act as a proxy to example.com. All requests will be responded immediately except some/endpoint which will have a delay of 2 seconds.