% Usage # Configuration The configuration file is a file containing a JSON object with the `post_paths` key. This key is an object mapping paths to objects describing where to write incoming objects to: ```json { "post_paths": { "": {…}, "": {…} }, "secrets": "" } ``` The optional `secrets` key is a path to a file containing a map of secret keys for projects: ```json { "": "", "": "" } ``` Each handler must have the `path` string which is where objects should be written to as well as a `filter` list which contains objects describing how to handle incoming objects. Each filter has a `kind` string to use if the filter succeeds. Optionally, the `header_name` key may be given to use indicate that an HTTP header may contain a string describing the event kind. In order to verify the contents of webhooks, the optional `verification` object may also be given. ```json "": { "path": "", "filters": […], "header_name": "
", "verification": {…} } ``` Filters may contain the `have_keys` list of strings, the `items` list of objects, and a `header_value`. If given, all of the [JSON Pointer][] lookups in the `have_keys` list must exist, otherwise the filter will not accept the incoming object. Similarly, the `items` object consisting of mappings from [JSON Pointer][] to a value within the input object and an expected value for it. If any value does match the lookup is either missing or does not match the expected value, the filter will not accept the incoming object. If given, the `header_value` is the expected value for the header specified in the handler's `header_name` field. If it is given and the header exists, it is used to determine whether the filter matches or not; the `have_keys` and `items` fields are ignored. If the `header_name` specified for the host is present, it may be used to build the `kind` by replacing `HEADER` in the `kind` field with the header's value by setting `use_header_value` to `true`. Note that if the header is not present or `HEADER` is not in `kind`, no replacement will occur. This should generally be used only in the catch-all filter. ```json { "kind": "", "use_header_value": , "have_keys": […], "items": { "": …, "": … }, "header_value": "
" } ``` Once a filter matches, the incoming JSON object is written to the handler's path given by the `path` variable using a filename based on the time the object is being written out and a random string in case there are objects being written out at the same time. The contents are a JSON object with two keys, `kind` as given by the matching filter and `data` containing the complete input object. Filters are tried in order and the first one which matches is used. If no filter matches, a `400 Bad Request` status code is returned. The verification object specifies the `secret_key_lookup`, the `verification_header`, and `compare` keys. If the `secret_key_lookup` value is a JSON pointer (i.e., it starts with `/`), it is used to extract from any given hook the key to use when looking up the secret in the JSON object loaded from the secrets file. If it is not a JSON pointer, it is used as the key directly. The `verification_header` key is the HTTP header to use as the expected value for verification. The `compare` key specifies how the value is intended to be validated. ```json { "secret_key_lookup": "", "verification_header": "", "compare": { "type": "…", … } } ``` The following values of the `type` for `compare` are valid: * `token`: Compares the secret against the header directly (shared secret). * `hmac`: Uses HMAC to verify the data contents of the received hook. This requires the `algorithm` key to also be set. The `sha1` and `sha256` algorithms are currently supported. In addition, if there is a static prefix on the header value, it may be given via the `prefix` key. # Reloading the Configuration The listener will reread its configuration upon a `PUT` request to the `/__reload` path. If the configuration is invalid, a `406 Not Acceptable` status will be returned and the old configuration will still be used. In order to reload the secrets, a `PUT` request may be sent to the `/__reload_secrets` path. It will also return a `406 Not Acceptable` if the file is invalid and use the old secrets database. # Communicating The tool will listen on the configured address for `POST` requests to the handlers. Any other method or unconfigured path will be ignored. # Example The following configuration file: ```json { "post_paths": { "filtered": { "path": "/path/to/filtered", "filters": [ { "kind": "check_keys_and_items", "have_keys": ["/required"], "items": { "/count": 5, }, }, { "kind": "check_keys", "have_keys": ["/required"], }, { "kind": "check_values", "items": { "/nested/key": true, "/nested/other_key": false, }, }, { "kind": "catchall" } ] }, "no_filters": { "path": "/path/for/no_filters", "filters": [] }, } } ``` will response to `POST` requests to `/filtered` and `/no_filters`. The following objects will receive the indicated `kind` into the relevant directory for the `filtered` endpoint whereas the `no_filters` endpoint will ignore all input because no filter explicitly matched: `{ "required": null }` is of kind `check_keys` because it contains all of the keys required by that filter, but the `/count` lookup from the `check_keys_and_items` filter fails. `{ "required": null, "count": 4 }` is of kind `check_keys` because it contains all of the keys required by that filter, but the `/count` lookup gives a value of `4` rather than the expected `5`. `{ "nested": { "key": true, "other_key": false } }` is of kind `check_values` because it is missing the `required` key used for `check_keys` and `check_keys_and_items` and matches all of the required items. `{}` is of kind `catchall` because no other filter matched it and none of the required keys (none) nor the items failed to match the object. [JSON Pointer]: https://tools.ietf.org/html/rfc6901