@@ -2122,31 +2122,178 @@ In this example, we store the visitor’s ID (based on their IP address)
2122
2122
in the C<vars> keyword during the C<before> hook. That value is later
2123
2123
used in the C</vip-area> route to personalize the response.
2124
2124
2125
+ =head3 Request Hooks
2126
+
2127
+ At the ticket booth just inside the entrance of Danceyland, the friendly
2128
+ gatekeeper scans every visitor's pass and gives them a sticker as they pass
2129
+ into the park:
2130
+
2131
+ hook before => sub {
2132
+ var sticker => 1;
2133
+ };
2134
+
2135
+ The C<before> hook runs before any other code just before each request is
2136
+ handled. In this example, we set a var, C<sticker>, that can be used later
2137
+ in the request.
2138
+
2139
+ As each visitor leaves, a park employee stamps each person's hand so they
2140
+ can be readmitted later in the day:
2141
+
2142
+ hook after => sub {
2143
+ my $user = var user;
2144
+ $user->stamp_hand;
2145
+ };
2146
+
2147
+ For this example, An object representing a user was stored in a var earlier
2148
+ in the request. On the user's way out (via the C<after> hook), their hand
2149
+ gets stamped, and could be checked the next time the user enters the park
2150
+ to skip buying another ticket.
2151
+
2125
2152
=head3 Template Hooks
2126
2153
2127
- Template hooks allow you to manipulate data before or after templates
2128
- are rendered:
2154
+ At Danceyland’s Caricature Corner, the brilliant artist B<Picasso McGlitterpants>
2155
+ creates a sketch of every guest who stops by. The caricature goes through
2156
+ several phases before it’s ready to hang on your wall:
2157
+
2158
+ =over
2159
+
2160
+ =item * Before the sketch is drawn: Picasso sharpens their pencils
2161
+
2162
+ =item * While drawing: the artist sneaks in little embellishments
2163
+
2164
+ =item * When the sketch is done: Picasso proudly signs their masterpiece
2165
+
2166
+ =item * Before handing it to you: the park staff pops it into a fancy frame
2167
+
2168
+ =back
2169
+
2170
+ Before the sketching starts, Picasso ensures all the materials are in order:
2129
2171
2130
2172
hook before_template_render => sub {
2131
2173
my $tokens = shift;
2132
- $tokens->{footer_note} = "Thanks for visiting Danceyland!";
2174
+
2175
+ # Picasso McGlitterpants sharpens their pencils and sets up the
2176
+ # paper before drawing begins.
2177
+ $tokens->{materials_ready} = 1;
2133
2178
};
2134
2179
2135
- In this example, the C<footer_note> is added to the template tokens
2136
- before it gets rendered. That token is available in the template as
2137
- C<[% footer_note %]>.
2180
+ Template hooks allow you to manipulate data before or after a view
2181
+ (i.e., template) is rendered. C<materials_ready> is added as a template
2182
+ token before the view gets rendered. That token is made available in the
2183
+ template as C<[% materials_ready %]>.
2184
+
2185
+ When the sketch is finished, Picasso adds their signature (with extra glitter,
2186
+ of course) to make sure the caricature is authentic:
2187
+
2188
+ hook after_template_render => sub {
2189
+ my $content = shift;
2190
+ $$content .= "\n\n-- Signed by Picasso McGlitterpants 🎨✨";
2191
+ };
2192
+
2193
+ This happens after the view/template is rendered, but before it is shown
2194
+ to the user.
2195
+
2196
+ Before the sketch is mounted, the artist sprinkles it with sparkles, making
2197
+ sure the presentation twinkles with Danceyland charm:
2198
+
2199
+ hook before_layout_render => sub {
2200
+ my ($tokens, $content) = @_;
2201
+
2202
+ $tokens->{special_effects} = 'sparkles';
2203
+ };
2204
+
2205
+ Layout hooks apply after views are rendered, when the layout is going
2206
+ to be applied. The C<before_layout_render> hook is run prior to the layout
2207
+ being applied. It's a useful place to check for things such as whether or
2208
+ not is authorized to view select content.
2209
+
2210
+ At the very end, just before the guest receives their caricature, the staff pops
2211
+ it into a silvery frame so it’s ready to hang at home:
2212
+
2213
+ hook after_layout_render => sub {
2214
+ my $content = shift;
2215
+
2216
+ $$content = '<div class="silver-frame">' . $$content . "</div>";
2217
+ };
2218
+
2219
+ The C<after_layout_render> hook is the last chance to alter content before
2220
+ being sent to the browser.
2138
2221
2139
2222
=head3 Error Handling Hooks
2140
2223
2141
- Error hooks let you modify how errors are handled:
2224
+ Even in Danceyland, sometimes the roller coaster gets stuck at the top, or
2225
+ the cotton candy machine makes a little too much fluff. That’s when our
2226
+ friendly park attendants step in!
2227
+
2228
+ Error hooks let you step in whenever something goes wrong in an application.
2229
+ Just like Danceyland staff rushing over with a smile and a toolkit, your
2230
+ error hook can log what happened, show a helpful message, or gently guide
2231
+ the guest to the right exit.
2232
+
2233
+ hook on_route_exception => sub {
2234
+ my ($error) = @_;
2235
+ warning "Picasso McGlitterpants spilled glitter on the server: $error";
2236
+ };
2237
+
2238
+ Or you can catch a general error and provide your own response:
2239
+
2240
+ hook before_error => sub {
2241
+ my ($error) = @_;
2242
+ $error->message("Oops! One of the rides jammed. " .
2243
+ "Please enjoy a free churro while we fix it.");
2244
+ };
2245
+
2246
+ Other error hooks include:
2247
+
2248
+ =over
2249
+
2250
+ =item * init_error
2251
+
2252
+ This runs right after a new L<Dancer2::Core::Error> object is built. The new
2253
+ error object is passed to the hook as an argument.
2142
2254
2143
- hook on_handler_exception => sub {
2144
- my $error = shift;
2145
- warning "Oops! We encountered an error: $error";
2255
+ =item * after_error
2256
+
2257
+ This hook is called right after error is thrown, and receives a
2258
+ L<Dancer2::Core::Response> object as an argument.
2259
+
2260
+ =item * on_hook_exception
2261
+
2262
+ This hook is special, and is only called when an exception is caught in
2263
+ another hook, just before logging it and rethrowing it higher.
2264
+
2265
+ This hook receives as arguments:
2266
+
2267
+ =over
2268
+
2269
+ =item * A L<Dancer2::Core::App> object
2270
+
2271
+ =item * The error string
2272
+
2273
+ =item The name of the hook where the exception occurred
2274
+
2275
+ The hook name is the full hook name (e.g. C<core.app.route_exception>).
2276
+
2277
+ =back
2278
+
2279
+ If the function provided to C<on_hook_exception> causes an exception itself, then
2280
+ this will be ignored (thus preventing a potentially recursive situation).
2281
+ However, it is still possible for the function to set a custom response and
2282
+ halt it (and optionally die), thus providing a method to render custom content
2283
+ in the event of an exception in a hook:
2284
+
2285
+ hook on_hook_exception => sub {
2286
+ my ($app, $error, $hook_name) = @_;
2287
+ $app->response->content("Oh noes! The popcorn machine " .
2288
+ "overheated and overflowed!");
2289
+ $app->response->halt;
2146
2290
};
2147
2291
2148
- This hook runs when an exception occurs in a route handler, logging the
2149
- error.
2292
+ =back
2293
+
2294
+ Think of error hooks as the ever-present Danceyland helpers: they
2295
+ make sure that when a mishap occurs, guests are cared for and can
2296
+ keep smiling on their way to the next attraction.
2150
2297
2151
2298
=head3 File Rendering Hooks
2152
2299
@@ -2164,56 +2311,72 @@ File rendering hooks are triggered when static files are served:
2164
2311
2165
2312
=head3 Logging Hooks
2166
2313
2167
- You can customize logging behavior using hooks:
2314
+ Logging hooks can be used to give additional information or context to
2315
+ Danceyland maintenance workers when something breaks down, or to ride
2316
+ operators to help ensure smooth operation of rides:
2168
2317
2169
- hook before_logger => sub {
2170
- my $ level = shift ;
2171
- debug "A log message at level $level is about to be written." ;
2318
+ hook 'engine.logger.before' => sub {
2319
+ my ( $logger, $ level, @messages ) = @_ ;
2320
+ push @messages, 'Request ID: ' . vars->{request_id} ;
2172
2321
};
2173
2322
2174
- =head3 Serializer Hooks
2323
+ hook 'engine.logger.after' => sub {
2324
+ my ( $logger, $level, @messages ) = @_;
2325
+ if( $level eq 'error' ) {
2326
+ # Add code to send an email here
2327
+ }
2328
+ };
2175
2329
2176
- Serializer hooks allow you to manipulate serialized data before it’s
2177
- sent to the client:
2330
+ These hooks are useful when you want to prepend or append information to
2331
+ a log message, write messages out in a specific format, or take additional
2332
+ action based on message severity.
2178
2333
2179
- hook before_serialize => sub {
2180
- my $data = shift;
2181
- debug "Serializing this data: " . to_json($data);
2182
- };
2334
+ =head3 Serializer Hooks
2183
2335
2184
- =head2 Handlers
2336
+ Every great visit to Danceyland ends with a souvenir! Serializer hooks
2337
+ are the way Danceyland decides how to wrap up your experience before
2338
+ sending you home. Maybe you get your caricature rolled up in a tube,
2339
+ maybe it’s slipped into a glossy folder, or maybe Picasso McGlitterpants
2340
+ mails it to you as a postcard.
2185
2341
2186
- Handlers are the rides that keep Danceyland running. Dancer2 provides
2187
- several built- in handlers to manage files, pages, and routes. You can
2188
- also create your own handlers to extend the park’s offerings .
2342
+ That’s what serializers do: they take the "thing" (your response)
2343
+ and package it in the right format (JSON, YAML, plain text, etc.)
2344
+ so you can carry it with you outside the park.
2189
2345
2190
- =head2 File Handler
2346
+ For example:
2191
2347
2192
- The L<Dancer2::Handler::File> component is used to serve static files,
2193
- like images and stylesheets, from the C<public> directory. It comes with
2194
- two hooks:
2348
+ set serializer => 'JSON';
2195
2349
2196
- =over 4
2350
+ Now, every souvenir is neatly wrapped in shiny JSON paper.
2197
2351
2198
- =item before_file_render
2352
+ And if you want a custom wrapper, you can hook into the
2353
+ serializer process yourself:
2199
2354
2200
- Called before the file is served:
2355
+ hook before_serializer => sub {
2356
+ my ($content) = @_;
2357
+ debug "Preparing to wrap up: $content";
2358
+ };
2201
2359
2202
- hook before_file_render => sub {
2203
- my $path = shift ;
2204
- debug "Serving file : $path ";
2360
+ hook after_serializer => sub {
2361
+ my ($serialized) = @_ ;
2362
+ debug "Souvenir has been wrapped : $serialized ";
2205
2363
};
2206
2364
2207
- =item C<after_file_render>
2365
+ So whenever you see serializer hooks, think of the Danceyland
2366
+ souvenir shop — the place that makes sure you don’t just have
2367
+ a memory, but also a neatly wrapped keepsake to take home.
2368
+
2369
+ =head2 Handlers
2208
2370
2209
- Called after the file is served:
2371
+ Handlers are the rides that keep Danceyland running. Dancer2 provides
2372
+ several built-in handlers to manage files, pages, and routes. You can
2373
+ also create your own handlers to extend the park’s offerings.
2210
2374
2211
- hook after_file_render => sub {
2212
- my $response = shift;
2213
- debug "File served, status: " . $response->status;
2214
- };
2375
+ =head2 File Handler
2215
2376
2216
- =back
2377
+ The L<Dancer2::Handler::File> component is used to serve static files,
2378
+ like images and stylesheets, from the C<public> directory. It comes with
2379
+ two hooks; see the L</Hooks> section for more information.
2217
2380
2218
2381
=head2 Auto Page Handler
2219
2382
0 commit comments