Core Concepts and Usage

This guide covers the fundamental concepts of how Webhookd works, from how scripts are mapped to URLs to how data is passed to them.

Script Directory Structure

Webhookd maps the directory structure of your scripts folder directly to webhook URLs. The location of your executable script determines its endpoint.

By default, webhookd looks for scripts in a ./scripts directory. You can change this with the -hook-scripts flag or the WHD_HOOK_SCRIPTS environment variable.

Example Structure:

/path/to/scripts
|-- /github
|   |-- build.sh
|   |-- deploy.sh
|-- echo.sh
|-- a/very/nested/script.js

Corresponding Webhook URLs:

  • /github/build -> executes build.sh
  • /github/deploy -> executes deploy.sh
  • /echo -> executes echo.sh
  • /a/very/nested/script -> executes script.js

Script Extensions

You can omit the script's extension in the URL. By default, webhookd will look for a .sh file. You can change the default extension with the -hook-default-ext flag or WHD_HOOK_DEFAULT_EXT environment variable.

If you want to call a script with a non-default extension, you must include it in the URL (e.g., /a/very/nested/script.js).

Executable Scripts

Any file in the scripts directory can be a webhook, as long as it has execute permissions (chmod +x). For interpreted languages like Python, Node.js, or Ruby, make sure to include a shebang line at the top of your script.

Example Node.js Script:

#!/usr/bin/env node

console.log("This is a Node.js webhook!");

Passing Parameters to Scripts

Webhookd provides several ways to pass data from an HTTP request to your script. All parameter keys are converted to snake_case environment variables.

1. URL Query Parameters

Parameters in the URL's query string are directly converted into environment variables.

  • Request: curl "http://localhost:8080/myhook?user_id=123&force_build=true"
  • Available in script: $user_id (value: 123), $force_build (value: true)

2. HTTP Headers

HTTP headers are also converted to environment variables. Header names are converted to snake_case.

  • Request: curl -H "User-Agent: My-Awesome-Client" http://localhost:8080/myhook
  • Available in script: $user_agent (value: My-Awesome-Client)

3. Request Body

The request body is handled based on its Content-Type header:

  • application/x-www-form-urlencoded: Key-value pairs from the form data are converted into environment variables, just like query parameters.
  • application/json or text/*: The entire raw request body is passed as the first command-line argument ($1) to your script.

Example with JSON Body:

  • Request:

    curl -X POST -H 'Content-Type: application/json' \
      --data '{"message": "hello world"}' \
      http://localhost:8080/myhook

  • Accessing in script: The JSON string '{"message": "hello world"}' is available as $1.

    #!/bin/bash
    PAYLOAD=$1
    MESSAGE=$(echo "$PAYLOAD" | jq -r '.message')
    echo "The message is: $MESSAGE"

Injected Environment Variables

In addition to parameters from the request, Webhookd injects its own set of useful variables into the script's environment:

  • hook_id: A unique, auto-incrementing ID for each hook execution.
  • hook_name: The name of the hook being executed (e.g., github/build).
  • hook_method: The HTTP method used for the request (e.g., GET, POST).
  • x_forwarded_for: The client's IP address, derived from the X-Forwarded-For header or the remote address.
  • x_webauth_user: If authentication is enabled, this contains the authenticated username.