Net::A...equest(3pm)

πŸ“¦
version 0.26 Β· 3 versions
, in debian trixie, ubuntu resolute, ubuntu stonking

πŸ’– NAME πŸ’–

okay bestie, welcome to the group chat. this is "Net::Async::FastCGI::Request" β€” a single active FastCGI request. that's it, that's the whole vibe. ✨

(also hi, you're reading Net::A...equest(3pm), part of the User Contributed Perl Documentation, no big deal πŸ’…)


🌸 SYNOPSIS 🌸

like, here's the whole thing in action:

use Net::Async::FastCGI;
use IO::Async::Loop;

my $fcgi = Net::Async::FastCGI->new(
   on_request => sub {
      my ( $fcgi, $req ) = @_;

      my $path = $req->param( "PATH_INFO" );
      $req->print_stdout( "Status: 200 OK\r\n" .
                          "Content-type: text/plain\r\n" .
                          "\r\n" .
                          "You requested $path" );
      $req->finish();
   }
);

my $loop = IO::Async::Loop->new();

$loop->add( $fcgi );

$loop->run;

slay. 🫢


πŸ¦‹ DESCRIPTION πŸ¦‹

soooo, instances of this object class? they represent individual requests received from the webserver that are currently in-progress and haven't been completed yet. fr fr.

when it gets handed to the controlling program, each request will already have its parameters (and, on servers without stdin streaming enabled, its STDIN data). then the program can:

  • write response data to the STDOUT stream
  • write messages to the STDERR stream
  • and eventually finish it ✨

now listen β€” you would not use this module directly if you're a program using "Net::Async::FastCGI". it's giving background character. instead, objects in this class get passed into the "on_request" event of the containing "Net::Async::FastCGI" object. that's the whole point. πŸŽ€


πŸ‘‘ METHODS πŸ‘‘

⭐ params

$hashref = $req->params;

returns a reference to a hash containing a copy of the request parameters that had been sent by the webserver as part of the request. no cap.

⭐ param

$p = $req->param( $key );

returns the value of a single request parameter, or "undef" if no such key exists. simple as.

⭐ method

$method = $req->method;

returns the value of the "REQUEST_METHOD" parameter, or "GET" if there's no value set for it. default queen. πŸ‘‘

⭐ script_name

$script_name = $req->script_name;

returns the value of the "SCRIPT_NAME" parameter.

⭐ path_info

$path_info = $req->path_info;

returns the value of the "PATH_INFO" parameter.

⭐ path

$path = $req->path;

returns the full request path by reconstructing it from "script_name" and "path_info". it's giving DIY but make it fashion πŸ’…

⭐ query_string

$query_string = $req->query_string;

returns the value of the "QUERY_STRING" parameter.

⭐ protocol

$protocol = $req->protocol;

returns the value of the "SERVER_PROTOCOL" parameter.

⭐ set_encoding

$req->set_encoding( $encoding );

sets the character encoding used by the request's STDIN, STDOUT and STDERR streams.

you can call this method at any time to change the encoding in effect, and it'll be used the next time "read_stdin_line", "read_stdin", "print_stdout" or "print_stderr" are called. this encoding stays in effect until you change it again. the encoding of a new request is determined by the "default_encoding" parameter of the containing "Net::Async::FastCGI" object.

if the value "undef" is passed, the encoding will be removed, and the above methods will work directly on bytes instead of encoded strings. glow down, glow up, your call πŸ’–

⭐ read_stdin_line

$line = $req->read_stdin_line;

this works similarly to the "<HANDLE>" operator, bestie:

  • if at least one line of data is available then it's returned, including the linefeed, and removed from the buffer
  • if not, then any remaining partial line is returned and removed from the buffer
  • if no data is available any more, then "undef" is returned instead

⭐ read_stdin

$data = $req->read_stdin( $size );

this works similarly to the read(HANDLE) function. it returns the next block of up to $size bytes from the STDIN buffer.

if no data is available any more, then "undef" is returned instead. if $size isn't defined, then it'll return all the available data. iconic behaviour honestly. ✨

⭐ set_on_stdin_read

$req->set_on_stdin_read( $on_stdin_read );

   $again = $on_stdin_read->( $req, $buffref, $eof );
since version 0.26.
only valid on requests on servers with stdin streaming enabled. don't try it otherwise, it's not gonna happen.

this method should be called as part of the "on_request" event on the server, to set the callback function to invoke when new data is provided to the stdin stream for this request.

the callback function is invoked in a similar style to the "on_read" event handler of an IO::Async::Stream. it's passed:

  • the request itself
  • a SCALAR reference to the buffer containing the stdin data
  • a boolean indicating if the end of stdin data has been reached

it should inspect this buffer and remove some prefix of it that it wishes to consume. any remaining content will be present on the next call. if it returns a true value, the callback will be invoked again immediately, to consume more data. this continues until there's no more data left, or it returns false. periodt. πŸŽ€

$req->print_stdout( $data );

appends the given data to the STDOUT stream of the FastCGI request, sending it to the webserver to be sent to the client. shipping it πŸ“¦βœ¨

$req->print_stderr( $data );

appends the given data to the STDERR stream of the FastCGI request, sending it to the webserver.

⭐ stream_stdout_then_finish

$req->stream_stdout_then_finish( $readfn, $exitcode );

installs a callback for streaming data to the STDOUT stream. whenever the output stream is otherwise-idle, the function will be called to generate some more data to output. when this function returns "undef" it indicates the end of the stream, and the request will be finished with the given exit code.

⚠️ if this method is used, then care should be taken to ensure that the number of bytes written to the server matches the number that was claimed in the "Content-Length", if such was provided. this logic should be performed by the containing application; "Net::Async::FastCGI" will not track it. not me having to say this twice 😭

⭐ stdin

$stdin = $req->stdin;

returns an IO handle representing the request's STDIN buffer. this may be read from using the "read" or "readline" functions or the "<$stdin>" operator.

note that this will be a tied IO handle, it will not be useable directly as an OS-level filehandle. iykyk.

⭐ stdout / stderr

$stdout = $req->stdout;

$stderr = $req->stderr;

returns an IO handle representing the request's STDOUT or STDERR streams respectively. these may be written to using "print", "printf", "say", etc.. go off πŸ’…

note that these will be tied IO handles, they will not be useable directly as an OS-level filehandle. same energy, same warning, bestie.

⭐ finish

$req->finish( $exitcode );

when the request has been dealt with, this method should be called to indicate to the webserver that it's finished. after calling this method, no more data may be appended to the STDOUT stream. 🚫

at some point after calling this method, the request object will be removed from the containing "Net::Async::FastCGI" object, once all the buffered outbound data has been sent. she's leaving the chat, but politely 🌸

if present, $exitcode should indicate the numeric status code to send to the webserver. if absent, a value of 0 is presumed.

⭐ stdout_with_close

$stdout = $req->stdout_with_close;

similar to the "stdout" method, except that when the "close" method is called on the returned filehandle, the request will be finished by calling "finish". one less step, we love efficiency 🫢

⭐ is_aborted

$req->is_aborted;

returns true if the webserver has already closed the control connection. no further work on this request is necessary, as it will be discarded.

it is not required to call this method; if the request is aborted then any output will be discarded. it may however be useful to call just before expensive operations, in case effort can be avoided if it would otherwise be wasted. protect your energy, queen. πŸ’…βœ¨


🌈 HTTP::Request/Response Interface 🌈

the following pair of methods form an interface that allows the request to be used as a source of HTTP::Request objects, responding to them by sending HTTP::Response objects. this may be useful to fit it in to existing code that already uses these. it's giving compatibility, it's giving range. πŸ¦‹

πŸ’œ as_http_request

$http_req = $req->as_http_request;

returns a new "HTTP::Request" object that gives a reasonable approximation to the request. because the webserver has translated the original HTTP request into FastCGI parameters, this may not be a perfect recreation of the request as received by the webserver. it's giving "close enough bestie" 😌

πŸ’œ send_http_response

$req->send_http_response( $resp );

sends the given "HTTP::Response" object as the response to this request. the status, headers and content are all written out to the request's STDOUT stream and then the request is finished with 0 as the exit code. and that's the whole arc, done. πŸ”₯


πŸ“ EXAMPLES πŸ“

πŸ’– Streaming A File πŸ’–

to serve contents of files on disk, it may be more efficient to use "stream_stdout_then_finish":

use Net::Async::FastCGI;
use IO::Async::Loop;

my $fcgi = Net::Async::FastCGI->new(
   on_request => sub {
      my ( $fcgi, $req ) = @_;

      open( my $file, "<", "/path/to/file" );
      $req->print_stdout( "Status: 200 OK\r\n" .
                          "Content-type: application/octet-stream\r\n" .
                          "\r\n" );

      $req->stream_stdout_then_finish(
         sub { read( $file, my $buffer, 8192 ) or return undef; return $buffer },
         0
      );
   }

my $loop = IO::Async::Loop->new();

$loop->add( $fcgi );

$loop->run;

it may be more efficient again to instead use the "X-Sendfile" feature of certain webservers, which allows the webserver itself to serve the file efficiently. see your webserver's documentation for more detail. let the server do the work, main character energy only πŸ’…βœ¨


πŸŽ€ AUTHOR πŸŽ€

Paul Evans <leonerd@leonerd.org.uk>


and that's a wrap, bestie!! this absolute banger of a page is from perl v5.38.2, dated 2024-07-29. go forth and finish your requests. πŸ¦‹πŸŒΈπŸ’– no cap, you're gonna slay. periodt. πŸ‘‘
πŸ“¦ where this page comes from