Skip to content

Latest commit

 

History

History

bridge

GitHub tag Build Status Bridge Security License Join our slack

Svix Bridge

Bridge is an agent to help integrate webhooks into your existing messaging infrastructure.

Bridge is organized in terms of senders and receivers.

Senders are useful when you have a data source (an "input") such as a message queue and want to generate Svix webhooks from those messages.

Receivers act as HTTP endpoints which wait for Svix webhooks to arrive, then publish the payload on to a specified "output."

Receivers also (optionally) perform validation of the webhooks using Svix's signature verification.

Both senders and receivers are defined in terms of their input, and optional JavaScript transformation, and their output.


Transformations are configured as either a single string of JS source code:

transformation: |
    function handler(input) {
      return {
        appId: input.key,
        message: {
          eventType: input.event_type,
          payload: input.data
        }
      };
    }

In this situation, the input value will be pre-parsed as JSON.

You can also configure transformations using the verbose form, allowing control of the format:

transformation:
  format: "json"
  src: |
    function handler(input) {
      return {
        appId: input.key,
        message: {
          eventType: input.event_type,
          payload: input.data
        }
      };
    }

The format field can be set to either string (ie. the raw payload) or json (the default behavior).

For example, using the string format you can parse data out of the input using whatever method you like:

transformation:
  # Let's say the input is an XML message like:
  # `<msg appId="app_123" eventType="a.b"><payload>{"x": 123}</payload></msg>`

  format: "string"
  src: |
    function handler(input) {
      let parser = new DOMParser();
      let doc = parser.parseFromString(input, "text/xml");
      let msg = doc.firstChild;
      let payload = JSON.parse(msg.getElementsByTagName("payload")[0].textContent)

      return {
        appId: msg.attributes.appId,
        message: {
          eventType: msg.attributes.eventType,
          payload,
        }
      };
    }

Transformations must define a function named handler which receives a single argument, the type of which is controlled by the configured format field.

Note that regardless of the format, the return type of handler must be an Object.


Currently the supported Sender inputs and Receiver outputs are the following messaging systems:

  • GCP Pub/Sub
  • RabbitMQ
  • Redis
  • SQS
  • Kafka

Important to note that queues, exchanges, topics, etc should be created and configured independently, prior to using launching Bridge. Bridge will not automatically attempt to create these resources, it will only try (and fail) to read from or publish to the stream/queue in this case.

Installation

Docker images are available on docker hub

$ docker pull svix/svix-bridge

If you don't want to use docker, see Building from Source.

Usage and Configuration

The CLI itself will look for a config file named svix-bridge.yaml or svix-bridge.json in the current working directory. Additionally, Bridge can load its configuration from a different location via --cfg-file (or SVIX_BRIDGE_CFG_FILE), or otherwise the config can be given as a string via --cfg (or SVIX_BRIDGE_CFG).

Examples:

# Using the default config file location
$ svix-bridge

# Specifying an alternate location
$ svix-bridge --cfg-file path/to/svix-bridge.json

# Config data supplied directly
$ svix-bridge --cfg '{"log_format": "json", "senders": []}'

Variable Expansion

svix-bridge supports environment variable expansion inside the config file.

Using "dollar brace" notation, e.g. ${MY_VARIABLE}, a substitution will be made from the environment. If the variable lookup fails, the raw variable text is left in the config as-is.

As an example, here's a RabbitMQ sender configured with environment variables:

senders:
  - name: "send-webhooks-from-${QUEUE_NAME}"
    input:
      type: "rabbitmq"
      uri: "${MQ_URI}"
      queue_name: "${QUEUE_NAME}"
    output:
      type: "svix"
      token: "${SVIX_TOKEN}"

Each sender and receiver can optionally specify a transformation. Transformations should define a function called handler that accepts an object and returns an object.

Senders should produce JSON following an expected shape:

{
    "appId": "app_XYZ",
    "message": {
        "eventType": "my.event",
        "payload": {"code": 123, "message": "something happened..."}
    }
}

For detail on the message field, see: https://api.svix.com/docs#tag/Message/operation/v1.message.create

Receivers can accept arbitrary body data but the outputs require a JSON object with a payload field representing the message to publish.

{
    "payload": {"msg": "my cool message, published by svix-bridge!"}
}

When a transformation is not configured, the default behavior is to parse the request body as JSON and set this value as the payload field before forwarding to the output.

By configuring a transformation, you should be able to consume a variety of POST bodies and produce a valid output, but just remember to make sure the return value has your data attached to the payload field.

See the example configs for how to configure each input and output in more detail:

Building from source

You would need a working Rust compiler in order to build Svix Bridge. The easiest way is to use rustup.

# Clone the repository
git clone https://github.com/svix/svix-webhooks
# Change to the source directory
cd svix-webhooks/bridge/
# Build
cargo install --path svix-bridge

Some system dependencies are required for Bridge to build successfully. Consult the Dockerfile for a good reference of what's required at build time.

Building with Docker

# Clone the repository
git clone https://github.com/svix/svix-webhooks
# Change to the source directory
cd svix-webhooks/bridge/
# Build
docker build --tag svix-bridge:local .