Skip to content

task: header symbolization #41

Closed
Closed
@GrantBirki

Description

@GrantBirki

This issue tracks work to make the headers parameter of the base handler a symbolized hash by default. This follows the same pattern as the config, and payload parameters. Just like with the payload parameter, the headers param should have a new environment variable and global config option created to "opt-out" of symbolization. In order to symbolize, all headers should have - converted to _. Right now, we normalize all headers by making them downcase, and trimmed before passing them to the handler plugins. This feature would add one new step to symbolize them (by default) and then have opt-out config options to skip symbolization.

# example file path: plugins/handlers/example.rb
class Example < Hooks::Plugins::Handlers::Base
  # Process a webhook payload
  #
  # @param payload [Hash, String] webhook payload (symbolized keys by default)
  # @param headers [Hash<String, String>] HTTP headers NEW! this should be a symbolized hash by default now, just like the payload param above
  # @param config [Hash] Endpoint configuration
  # @return [Hash] Response data
  def call(payload:, headers:, config:)
    return {
      status: "success"
    }
  end
end

Docs, yard doc strings, and comments should be updated to reflect these changes. All tests should still pass too.

From the internal docs of this project:


# file: docs/handler_plugins.md

payload Parameter

The payload parameter can be a Hash or a String. If the payload is a String, it will be parsed as JSON. If it is a Hash, it will be passed directly to the handler. The payload can contain any data that the webhook sender wants to send.

By default, the payload is parsed as JSON (if it can be) and then symbolized. This means that the keys in the payload will be converted to symbols. You can disable this auto-symbolization of the payload by setting the environment variable HOOKS_SYMBOLIZE_PAYLOAD to false or by setting the symbolize_payload option to false in the global configuration file.

TL;DR: The payload is almost always a Hash with symbolized keys, regardless of whether the original payload was a Hash or a JSON String.

For example, if the client sends the following JSON payload:

{
  "hello": "world",
  "foo": ["bar", "baz"],
  "truthy": true,
  "coffee": {"is": "good"}
}

It will be parsed and passed to the handler as:

{
  hello: "world",
  foo: ["bar", "baz"],
  truthy: true,
  coffee: {is: "good"}
}

headers Parameter

The headers parameter is a Hash that contains the HTTP headers that were sent with the webhook request. It includes standard headers like host, user-agent, accept, and any custom headers that the webhook sender may have included.

Here is an example of what the headers parameter might look like:

# example headers as a Hash
{
  "host" => "<HOSTNAME>", # e.g., "hooks.example.com"
  "user-agent" => "foo-client/1.0",
  "accept" => "application/json, text/plain, */*",
  "accept-encoding" => "gzip, compress, deflate, br",
  "client-name" => "foo",
  "x-forwarded-for" => "<IP_ADDRESS>",
  "x-forwarded-host" => "<HOSTNAME>", # e.g., "hooks.example.com"
  "x-forwarded-proto" => "https",
  "version" => "HTTP/1.1",
  "Authorization" => "Bearer <TOKEN>" # a careful reminder that headers *can* contain sensitive information!
}

It should be noted that the headers parameter is a Hash with String keys (not symbols). They are also normalized (lowercased and trimmed) to ensure consistency.

You can disable this normalization by either setting the environment variable HOOKS_NORMALIZE_HEADERS to false or by setting the normalize_headers option to false in the global configuration file.

config Parameter

The config parameter is a Hash (symbolized) that contains the endpoint configuration. This can include any additional settings or parameters that you want to use in your handler. Most of the time, this won't be used, but sometimes endpoint configs add opts that can be useful for the handler.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions