You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/handler_plugins.md
+57-9Lines changed: 57 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,26 +4,33 @@ This document provides in-depth information about handler plugins and how you ca
4
4
5
5
## Writing a Handler Plugin
6
6
7
-
Handler plugins are Ruby classes that extend the `Hooks::Plugins::Handlers::Base` class. They are used to process webhook payloads and can do anything you want. They follow a very simple interface that allows you to define a `call` method that takes three parameters: `payload`, `headers`, and `config`. The `call` method should return a hash with the response data. The hash that this method returns will be sent back to the webhook sender as a JSON response.
7
+
Handler plugins are Ruby classes that extend the `Hooks::Plugins::Handlers::Base` class. They are used to process webhook payloads and can do anything you want. They follow a very simple interface that allows you to define a `call` method that takes four parameters: `payload`, `headers`, `env`, and `config`.
8
+
9
+
**Important:** The `call` method should return a hash by default. Since the server now defaults to JSON format, any hash returned by the handler will be automatically converted to JSON with the correct `Content-Type: application/json` headers set by Grape. This ensures consistent API responses and proper JSON serialization.
8
10
9
11
-`payload`: The webhook payload, which can be a Hash or a String. This is the data that the webhook sender sends to your endpoint.
10
12
-`headers`: A Hash of HTTP headers that were sent with the webhook request.
11
13
-`env`: A modified Rack environment that contains a lot of context about the request. This includes information about the request method, path, query parameters, and more. See [`rack_env_builder.rb`](../lib/hooks/app/rack_env_builder.rb) for the complete list of available keys.
12
14
-`config`: A Hash containing 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.
13
15
16
+
The method should return a **hash** that will be automatically serialized to JSON format with appropriate headers. The server defaults to JSON format for both input and output processing.
17
+
14
18
```ruby
15
19
# example file path: plugins/handlers/example.rb
16
20
classExample < Hooks::Plugins::Handlers::Base
17
21
# Process a webhook payload
18
22
#
19
23
#@parampayload[Hash, String] webhook payload (pure JSON with string keys)
**Best Practice**: Always return a hash from your handler's `call` method. The hash will be automatically serialized to JSON and sent to the webhook sender with proper headers. This ensures consistent API responses and proper JSON formatting.
62
+
63
+
Example response format:
64
+
```json
65
+
{
66
+
"status": "success",
67
+
"message": "webhook processed successfully",
68
+
"data": {
69
+
"processed_at": "2023-10-01T12:34:56Z",
70
+
"items_processed": 5
71
+
}
72
+
}
73
+
```
74
+
75
+
> **Note**: The JSON format behavior can be configured using the `format` and `default_format` options in your global configuration. See the [Configuration documentation](./configuration.md) for more details.
76
+
46
77
### `payload` Parameter
47
78
48
79
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.
@@ -159,6 +190,8 @@ The `log.debug`, `log.info`, `log.warn`, and `log.error` methods are available i
159
190
160
191
All handler plugins have access to the `error!` method, which is used to raise an error with a specific message and HTTP status code. This is useful for returning error responses to the webhook sender.
161
192
193
+
When using `error!` with the default JSON format, both hash and string responses are handled appropriately:
194
+
162
195
```ruby
163
196
class Example < Hooks::Plugins::Handlers::Base
164
197
# Example webhook handler
@@ -167,11 +200,12 @@ class Example < Hooks::Plugins::Handlers::Base
# @param env [Hash] A modified Rack environment that contains a lot of context about the request
169
202
# @param config [Hash] Endpoint configuration
170
-
# @return [Hash] Response data
203
+
# @return [Hash] Response data (automatically converted to JSON)
171
204
def call(payload:, headers:, env:, config:)
172
205
173
206
if payload.nil? || payload.empty?
174
207
log.error("Payload is empty or nil")
208
+
# String errors are JSON-encoded with default format
175
209
error!("Payload cannot be empty or nil", 400)
176
210
end
177
211
@@ -182,21 +216,22 @@ class Example < Hooks::Plugins::Handlers::Base
182
216
end
183
217
```
184
218
185
-
You can also use the `error!` method to return a JSON response as well:
219
+
**Recommended approach**: Use hash-based error responses for consistent JSON structure:
186
220
187
221
```ruby
188
222
class Example < Hooks::Plugins::Handlers::Base
189
223
def call(payload:, headers:, env:, config:)
190
224
191
225
if payload.nil? || payload.empty?
192
226
log.error("Payload is empty or nil")
227
+
# Hash errors are automatically converted to JSON
193
228
error!({
194
229
error: "payload_empty",
195
230
message: "the payload cannot be empty or nil",
196
231
success: false,
197
232
custom_value: "some_custom_value",
198
233
request_id: env["hooks.request_id"]
199
-
}, 500)
234
+
}, 400)
200
235
end
201
236
202
237
return {
@@ -206,6 +241,17 @@ class Example < Hooks::Plugins::Handlers::Base
206
241
end
207
242
```
208
243
244
+
This will return a properly formatted JSON error response:
245
+
```json
246
+
{
247
+
"error": "payload_empty",
248
+
"message": "the payload cannot be empty or nil",
249
+
"success": false,
250
+
"custom_value": "some_custom_value",
251
+
"request_id": "uuid-here"
252
+
}
253
+
```
254
+
209
255
### `#Retryable.with_context(:default)`
210
256
211
257
This method uses a default `Retryable` context to handle retries. It is used to wrap the execution of a block of code that may need to be retried in case of failure.
@@ -220,7 +266,7 @@ class Example < Hooks::Plugins::Handlers::Base
0 commit comments