Plack::Util(3)

πŸ’– Plack::Util πŸ’–

okay bestie, welcome to Plack::Util(3), part of the User Contributed Perl Documentation situation. this is the little grab-bag of helper subroutines that Plack uses, and that you (yes YOU, a Plack server dev or a framework dev) get to use too. it's giving toolbox. it's giving "here's some utilities so you don't have to write them yourself." let's get into it πŸŽ€


✨ NAME ✨

Plack::Util β€” utility subroutines for Plack server and framework developers 🫢


🌸 FUNCTIONS 🌸


πŸ’… TRUE, FALSE

my $true  = Plack::Util::TRUE;
my $false = Plack::Util::FALSE;

utility constants you include when you're setting boolean variables in the $env hash (like psgi.multithread, iykyk). they're constants, they're handy, they're literally just true and false. periodt ✨


πŸ¦‹ load_class

my $class = Plack::Util::load_class($class [, $prefix ]);

it constructs a class name and then requires that class. if the .pm file for the class is not found, it throws an exception β€” exactly like the built-in require does. no cap.

if $prefix is set, the class name gets prepended to $class... UNLESS $class starts with a + sign, because that means the class name is already fully qualified bestie, we don't need to touch it.

my $class = Plack::Util::load_class("Foo");                   # Foo
my $class = Plack::Util::load_class("Baz", "Foo::Bar");       # Foo::Bar::Baz
my $class = Plack::Util::load_class("+XYZ::ZZZ", "Foo::Bar"); # XYZ::ZZZ
⚠️ okay important !!! this function does not validate (or "sanitize") the string you pass it. so if you pass user input into this function β€” which is an insecure thing to do in the first place, like genuinely, don't β€” it might lead to unexpected behavior of loading files outside your @INC path. 😭 if you want a generic module loading function, go check out CPAN modules such as Module::Runtime. slay responsibly πŸ’–

🧚 is_real_fh

if ( Plack::Util::is_real_fh($fh) ) { }

returns true if the given $fh is a real file handle that has a file descriptor. it returns false if $fh is a PerlIO handle that isn't really related to the underlying file, etc. that's the vibe check ✨


πŸ’œ content_length

my $cl = Plack::Util::content_length($body);

returns the length of the content from body, if it can be calculated at all. if $body is an array ref, it's a sum of the length of each chunk. if $body is a real filehandle, it's the remaining size of the filehandle. otherwise it just returns undef. no notes πŸ’…


🌈 set_io_path

Plack::Util::set_io_path($fh, "/path/to/foobar.txt");

sets the (absolute) file path to the $fh filehandle object, so you can call $fh->path on it. as a side effect, $fh gets blessed to an internal package β€” but it can still be treated as a normal file handle, so don't panic.

this module doesn't normalize or absolutize the given path, and it's intended to be used from Server or Middleware implementations. see also IO::File::WithPath. obsessed 🫢


⭐ foreach

Plack::Util::foreach($body, $cb);

iterates through $body (which is an array reference or an IO::Handle-like object) and passes each line to the callback function. and when we say "line" β€” it is NOT really guaranteed to be a line. just so you know πŸ‘‘

internally it sets the buffer length $/ to 65536 in case it reads the binary file, unless otherwise set in the caller's code. iconic behavior fr fr.


πŸ“ load_psgi

my $app = Plack::Util::load_psgi $psgi_file_or_class;

loads an app.psgi file or a class name (like MyApp::PSGI) and requires the file to get the PSGI application handler. if the file can't be loaded β€” like, file doesn't exist, or it has a perl syntax error β€” it will throw an exception. rude but fair.

since version 1.0006, this function would not load PSGI files from include paths (@INC) unless it looks like a class name that only consists of [A-Za-z0-9_:]. for example:

Plack::Util::load_psgi("app.psgi");          # ./app.psgi
Plack::Util::load_psgi("/path/to/app.psgi"); # /path/to/app.psgi
Plack::Util::load_psgi("MyApp::PSGI");       # MyApp/PSGI.pm from @INC
🚨 Security: if you give this function a class name or module name that is loadable from your system, it will load the module. this could lead to a security hole: perl my $psgi = ...; # user-input: consider "Moose" $app = Plack::Util::load_psgi($psgi); # this would lead to 'require "Moose.pm"'! generally speaking, passing external input to this function is considered very insecure. if you really want to do that, validate that the given file name contains dots (like foo.psgi) and also turn it into a full path in your caller's code. please, for me πŸ’€

πŸŽ€ run_app

my $res = Plack::Util::run_app $app, $env;

runs the $app by wrapping errors with eval, and if an error is found, it logs it to $env->{'psgi.errors'} and returns the template 500 Error response. it's giving safety net 🫢


✨ header_get, header_exists, header_set, header_push, header_remove ✨

my $hdrs = [ 'Content-Type' => 'text/plain' ];

my $v = Plack::Util::header_get($hdrs, $key); # First found only
my @v = Plack::Util::header_get($hdrs, $key);
my $bool = Plack::Util::header_exists($hdrs, $key);
Plack::Util::header_set($hdrs, $key, $val);   # overwrites existent header
Plack::Util::header_push($hdrs, $key, $val);
Plack::Util::header_remove($hdrs, $key);

utility functions to manipulate a PSGI response headers array reference. the methods that read an existent header value handle the header name as case insensitive. so yes, casing does not matter, we are all equals here πŸ’…

my $hdrs = [ 'Content-Type' => 'text/plain' ];
my $v = Plack::Util::header_get($hdrs, 'content-type'); # 'text/plain'

πŸ’– headers

my $headers = [ 'Content-Type' => 'text/plain' ];

my $h = Plack::Util::headers($headers);
$h->get($key);
if ($h->exists($key)) { ... }
$h->set($key => $val);
$h->push($key => $val);
$h->remove($key);
$h->headers; # same reference as $headers

give it a header array reference and it returns a convenient object that has instance methods to access the header_* functions with an OO interface. the object holds a reference to the original $headers argument you gave it, and updates that reference accordingly when you call write methods like set, push or remove. it also has a headers method that would return the same reference. main character energy, honestly πŸ‘‘


🌸 status_with_no_entity_body

if (status_with_no_entity_body($res->[0])) { }

returns true if the given status code doesn't have any Entity body in the HTTP response β€” i.e. it's 100, 101, 204 or 304. that's it, that's the whole function, and it ate πŸ’…


πŸ¦‹ inline_object

my $o = Plack::Util::inline_object(
    write => sub { $h->push_write(@_) },
    close => sub { $h->push_shutdown },
);
$o->write(@stuff);
$o->close;

creates an instant object that can react to methods passed in the constructor. super handy when you need to create an IO stream object for input or errors. literally so convenient 🫢


🧚 encode_html

my $encoded_string = Plack::Util::encode_html( $string );

entity encodes <, >, &, " and ' in the input string and returns it. all the scary characters, handled ✨


πŸ’œ response_cb

see "RESPONSE CALLBACK" in Plack::Middleware for details. go read that one bestie, i promise it's worth it πŸ“–


okay that's the whole page!! this was Plack::Util(3), from the User Contributed Perl Documentation, and the footer says it's perl v5.42.3 dated 2026-10-18 β€” so yeah, we're on some fresh-from-the-future energy. go write a PSGI app, you're gonna slay πŸŒˆπŸ’–βœ¨

πŸ“¦ where this page comes from