FU
view release on metacpan or search on metacpan
Decode a query string or C<application/x-www-form-urlencoded> format (they're
the same thing). Returns a hashref with decoded key/value pairs. Values for
duplicated keys are collected into a single array value. Bare keys that do not
have a value are decoded as C<builtin::true>. Example:
my $hash = query_decode 'bare&a=1&a=2&something=else';
# $hash = {
# bare => builtin::true,
# a => [ 1, 2 ],
# something => 'else'
# }
The input C<$string> is assumed to be a perl Unicode string. An error is thrown
if the resulting data decodes into invalid UTF-8.
=item query_encode($hashref)
The opposite of C<query_decode>. Takes a hashref of similar structure and
returns an ASCII-encoded query string. Keys with C<undef> or C<to_bool()> false
values are omitted in the output.
If a given value is a blessed object with a C<TO_QUERY()> method, that method
is called and it should return either C<undef>, a boolean or a string, which is
then encoded.
=back
=head1 HTTP Date Formatting
The HTTP date format is utter garbage, but with the right tools it doesn't
require I<too> much code to work with.
=over
=item httpdate_format($time)
Convert the given seconds-since-Unix-epoch C<$time> into a HTTP date string.
=item httpdate_parse($str)
Converts the given HTTP date string into a seconds-since-Unix-epoch integer.
This function is very strict about its input and only accepts "IMF-fixdate" as
per L<RFC7231|https://www.rfc-editor.org/rfc/rfc7231#section-7.1.1.1>, which is
what every sensible implementation written in the past decade uses.
This function plays fast and loose with timezone conversions, the parsed
timestamp I<might> be off by an hour or so for a few hours around a DST change.
This will not happen if your local timezone is UTC.
=back
=head1 Gzip Compression
Gzip compression can be done with a few different libraries. The canonical one
is I<zlib>, which is old and not well optimized for modern systems. There's
also I<zlib-ng>, a (much) more performant reimplementation that remains
API-compatible with I<zlib>. And there's I<libdeflate>, which offers a
different API that does not support streaming compression but is, in exchange,
even faster than I<zlib-ng>.
There are more implementations, of course, but this module only supports those
three and (attempts to) pick the best one that's available on your system.
=over
=item gzip_lib()
Returns an empty string if no supported gzip library was found on your system
(unlikely but possible), otherwise returns the selected implementation: either
C<"libdeflate">, C<"zlib-ng"> or C<"zlib">.
This function does not try very hard to differentiate between I<zlib> and
I<zlib-ng>, so it may report that I<zlib> is being used on systems where
C<libz.so> is, in fact, I<zlib-ng>.
=item gzip_compress($level, $data)
Returns a byte string with the gzip-compressed version of C<$data> at the given
gzip C<$level>, which is a number between 0 (no compression) and 12 (strongest
compression). Only I<libdeflate> supports levels higher than 9, for
I<zlib(-ng)> the level is capped at 9. 6 is typically used as a default.
Throws an error if no suitable library was found.
This function is B<NOT> safe to use from multiple threads!
=back
This module does not currently implement decompression. If you need that, or
streaming, or other functionality not provided here, there's
L<Compress::Raw::Zlib> and L<Compress::Zlib> in the core Perl distribution and
L<Gzip::Faster>, L<Gzip::Zopfli> and L<Gzip::Libdeflate> on CPAN.
=head1 Brotli Compression
Just a small wrapper around C<libbrotlienc.so>'s one-shot compression
interface.
=over
=item brotli_compress($level, $data)
Returns a byte string with the brotli-compressed version of C<$data> at the
given quality C<$level> (between 0 and 11).
Throws an error if C<libbrotlienc.so> could not be found or loaded.
=back
=head1 File Descriptor Passing
UNIX sockets (see L<IO::Socket::UNIX>) have the fancy property of letting you
send file descriptors over them, allowing you to pass, for example, a socket
from one process to another. This is a pretty low-level operation and not
something you'll often need, but two functions to use that feature are provided
here anyway because the L<FU> supervisor uses them:
=over
=item fdpass_send($send_fd, $pass_fd, $message)
Send a message and a file descriptor (C<$pass_fd>) over the given socket
(C<$send_fd>). C<$message> must not be empty, even if you don't intend to do
anything with it on receipt. Both C<$send_fd> and C<$pass_fd> must be numeric
file descriptors, as obtained by C<fileno()>.
=item ($fd, $message) = fdpass_recv($recv_fd, $max_message_len)
Read a file descriptor and message from the given C<$recv_fd>, which must be
the numeric file descriptor of a socket. This function can be used as a
replacement for C<sysread()>: the returned C<$fd> is undef if no file
descriptor was received. The returned C<$message> is undef on error or an empty
string on EOF.
Like regular socket I/O, a single C<fdpass_send()> message may be split across
multiple C<fdpass_recv()> calls; in that case the C<$fd> is only received on
the first call.
The C<O_CLOEXEC> flag is set on received file descriptors. Don't use this
function if the sender may include multiple file descriptors in a single
message, weird things can happen. Refer to L<this wonderful
discussion|https://gist.github.com/kentonv/bc7592af98c68ba2738f4436920868dc>
for more weirdness and edge cases.
=back
See also L<IO::FDPass> for a more portable solution, although that one does not
support passing along regular data.
( run in 0.531 second using v1.01-cache-2.11-cpan-e93a5daba3e )