Skip to content

Commit d644114

Browse files
committed
breaking change: include the env param in the method signature for .call
1 parent 6554eed commit d644114

21 files changed

+81
-50
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Here is a very high-level overview of how Hooks works:
5858
```ruby
5959
# file: plugins/handlers/my_custom_handler.rb
6060
class MyCustomHandler < Hooks::Plugins::Handlers::Base
61-
def call(payload:, headers:, config:)
61+
def call(payload:, headers:, env:, config:)
6262
# Process the incoming webhook - optionally use the payload and headers
6363
# to perform some action or validation
6464
# For this example, we will just return a success message
@@ -233,7 +233,7 @@ Create custom handler plugins in the `plugins/handlers` directory to process inc
233233
```ruby
234234
# file: plugins/handlers/hello_handler.rb
235235
class HelloHandler < Hooks::Plugins::Handlers::Base
236-
def call(payload:, headers:, config:)
236+
def call(payload:, headers:, env:, config:)
237237
# Process the incoming webhook - optionally use the payload and headers
238238
# to perform some action or validation
239239
# For this example, we will just return a success message
@@ -251,7 +251,7 @@ And another handler plugin for the `/goodbye` endpoint:
251251
```ruby
252252
# file: plugins/handlers/goodbye_handler.rb
253253
class GoodbyeHandler < Hooks::Plugins::Handlers::Base
254-
def call(payload:, headers:, config:)
254+
def call(payload:, headers:, env:, config:)
255255
# Ditto for the goodbye endpoint
256256
{
257257
message: "goodbye webhook processed successfully",

docs/design.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Note: The `hooks` gem name is already taken on RubyGems, so this project is name
3333
2. **Plugin Architecture**
3434

3535
* **Team Handlers**: `class MyHandler < Hooks::Plugins::Handlers::Base`
36-
* Must implement `#call(payload:, headers:, config:)` method
36+
* Must implement `#call(payload:, headers:, env:, config:)` method
3737
* `payload`: parsed request body (JSON Hash or raw String)
3838
* `headers`: HTTP headers as Hash with string keys
3939
* `config`: merged endpoint configuration including `opts` section
@@ -230,7 +230,7 @@ endpoints_dir: ./config/endpoints # directory containing endpoint configs
230230
* **Before**: enforce `request_limit`, `request_timeout`
231231
* **Signature**: call custom or default validator
232232
* **Hooks**: run `on_request` plugins
233-
* **Handler**: invoke `MyHandler.new.call(payload:, headers:, config:)`
233+
* **Handler**: invoke `MyHandler.new.call(payload:, headers:, env:, config:)`
234234
* **After**: run `on_response` plugins
235235
* **Rescue**: on exception, run `on_error`, rethrow or format JSON error
236236

@@ -528,9 +528,10 @@ Base class for all webhook handlers.
528528
class MyHandler < Hooks::Plugins::Handlers::Base
529529
# @param payload [Hash, String] Parsed request body or raw string
530530
# @param headers [Hash<String, String>] HTTP headers
531+
# @param env [Hash] Rack environment (includes request context)
531532
# @param config [Hash] Merged endpoint configuration
532533
# @return [Hash, String, nil] Response body (auto-converted to JSON)
533-
def call(payload:, headers:, config:)
534+
def call(payload:, headers:, env:, config:)
534535
# Handler implementation
535536
{ status: "processed", id: generate_id }
536537
end

docs/handler_plugins.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ class Example < Hooks::Plugins::Handlers::Base
1717
#
1818
# @param payload [Hash, String] webhook payload (pure JSON with string keys)
1919
# @param headers [Hash] HTTP headers (string keys, optionally normalized - default is normalized)
20+
# @param env [Hash] A modifed Rack environment that contains a lot of context about the request
2021
# @param config [Hash] Endpoint configuration
2122
# @return [Hash] Response data
22-
def call(payload:, headers:, config:)
23+
def call(payload:, headers:, env:, config:)
2324
return {
2425
status: "success"
2526
}
@@ -123,9 +124,10 @@ class Example < Hooks::Plugins::Handlers::Base
123124
#
124125
# @param payload [Hash, String] Webhook payload
125126
# @param headers [Hash<String, String>] HTTP headers
127+
# @param env [Hash] A modified Rack environment that contains a lot of context about the request
126128
# @param config [Hash] Endpoint configuration
127129
# @return [Hash] Response data
128-
def call(payload:, headers:, config:)
130+
def call(payload:, headers:, env:, config:)
129131
result = Retryable.with_context(:default) do
130132
some_operation_that_might_fail()
131133
end

docs/instrument_plugins.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ Once configured, your custom instruments are available throughout the applicatio
160160

161161
```ruby
162162
class MyHandler < Hooks::Plugins::Handlers::Base
163-
def call(payload:, headers:, config:)
163+
def call(payload:, headers:, env:, config:)
164164
# Use your custom stats methods
165165
stats.increment("handler.calls", { handler: "MyHandler" })
166166

lib/hooks/app/api.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ def self.create(config:, endpoints:, log:)
109109
response = handler.call(
110110
payload:,
111111
headers: processed_headers,
112+
env: rack_env,
112113
config: endpoint_config
113114
)
114115

lib/hooks/app/endpoints/catchall.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ def self.route_block(captured_config, captured_logger)
5858
response = handler.call(
5959
payload:,
6060
headers:,
61+
env: { # a very limited Rack environment is present for catchall endpoints
62+
"REQUEST_METHOD" => request.request_method,
63+
"hooks.request_id" => request_id,
64+
},
6165
config: {}
6266
)
6367

lib/hooks/plugins/handlers/base.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@ class Base
1616
#
1717
# @param payload [Hash, String] Parsed request body (JSON Hash) or raw string
1818
# @param headers [Hash] HTTP headers (string keys, optionally normalized - default is normalized)
19+
# @param env [Hash] Rack environment (contains the request context, headers, etc - very rich context)
1920
# @param config [Hash] Merged endpoint configuration including opts section (symbolized keys)
2021
# @return [Hash, String, nil] Response body (will be auto-converted to JSON)
2122
# @raise [NotImplementedError] if not implemented by subclass
22-
def call(payload:, headers:, config:)
23+
def call(payload:, headers:, env:, config:)
2324
raise NotImplementedError, "Handler must implement #call method"
2425
end
2526
end

lib/hooks/plugins/handlers/default.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class DefaultHandler < Hooks::Plugins::Handlers::Base
2020
#
2121
# @param payload [Hash, String] The webhook payload (parsed JSON or raw string)
2222
# @param headers [Hash<String, String>] HTTP headers from the webhook request
23+
# @param env [Hash] Rack environment (contains the request context, headers, config, etc - very rich context)
2324
# @param config [Hash] Endpoint configuration containing handler options
2425
# @return [Hash] Response indicating successful processing
2526
# @option config [Hash] :opts Additional handler-specific configuration options
@@ -29,10 +30,11 @@ class DefaultHandler < Hooks::Plugins::Handlers::Base
2930
# response = handler.call(
3031
# payload: { "event" => "push" },
3132
# headers: { "Content-Type" => "application/json" },
33+
# env: { "REQUEST_METHOD" => "POST", "hooks.request_id" => "12345" },
3234
# config: { opts: {} }
3335
# )
3436
# # => { message: "webhook processed successfully", handler: "DefaultHandler", timestamp: "..." }
35-
def call(payload:, headers:, config:)
37+
def call(payload:, headers:, env:, config:)
3638

3739
log.info("🔔 Default handler invoked for webhook 🔔")
3840

@@ -41,6 +43,10 @@ def call(payload:, headers:, config:)
4143
log.debug("received payload: #{payload.inspect}")
4244
end
4345

46+
if env
47+
log.debug("default handler got a request with the following request_id: #{env['hooks.request_id']}")
48+
end
49+
4450
{
4551
message: "webhook processed successfully",
4652
handler: "DefaultHandler",
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# frozen_string_literal: true
22

33
class Boomtown < Hooks::Plugins::Handlers::Base
4-
def call(payload:, headers:, config:)
4+
def call(payload:, headers:, env:, config:)
55
raise StandardError, "Boomtown error occurred"
66
end
77
end

spec/acceptance/plugins/handlers/github_handler.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class GithubHandler < Hooks::Plugins::Handlers::Base
88
# @param headers [Hash<String, String>] HTTP headers
99
# @param config [Hash] Endpoint configuration
1010
# @return [Hash] Response data
11-
def call(payload:, headers:, config:)
11+
def call(payload:, headers:, env:, config:)
1212
log.info("🚀 Processing GitHub webhook 🚀")
1313
return {
1414
status: "success"

0 commit comments

Comments
 (0)