NAME

Catalyst::Seal::Middleware - leaner bodies for the two costly default middlewares

DESCRIPTION

Catalyst::default_middleware puts seven wrappers around every application. Measured by leave-one-out, each rebuilt with its own instances because Plack::Middleware::wrap mutates the instance it is called on:

ContentLength              9.51 us/req
HTTPExceptions             7.44
FixMissingBodyInRedirect   3.32
RemoveRedundantBody        1.67
MethodOverride             1.27
Head                       0.53

23.74 us together, a fifth of the request. Two of them are worth rewriting and the rest are close to the floor cost of a response_cb layer, which is what you pay for having a middleware at all.

Both replacements go in as the call method of the stock class, so the stack is still built by Catalyst in the stock order with the stock instances. Nothing here fuses or reorders anything: the order those response callbacks run in is load bearing, and Plack::Util::response_cb strips Content-Length once per nesting level.

ContentLength

The stock filter builds a Plack::Util::headers object, which is a blessed closure set, to ask two questions about the header list and sometimes push one entry. One pass over the arrayref answers the same questions.

HTTPExceptions

Two Try::Tiny blocks per request, one around the application call and one around the streaming responder, each building two closures. Plain eval does the same job. This is the same change phase 0 made to Catalyst's own two try blocks, in the one place outside Catalyst that is on the request path.

AUTHOR

LNATION <email@lnation.org>

LICENSE AND COPYRIGHT

This software is Copyright (c) 2026 by LNATION <email@lnation.org>.

This is free software, licensed under:

The Artistic License 2.0 (GPL Compatible)