Conduit

 view release on metacpan or  search on metacpan

lib/Conduit/Client.pm  view on Meta::CPAN

#  You may distribute under the terms of either the GNU General Public License
#  or the Artistic License (the same terms as Perl itself)
#
#  (C) Paul Evans, 2026 -- leonerd@leonerd.org.uk

use v5.36;

use feature 'try';
use Future::AsyncAwait;
use Object::Pad 0.807 ':experimental(inherit_field)';

class Conduit::Client 0.03
   :strict(params);

no if $^V lt v5.40, warnings => "experimental::try", "experimental::builtin";

field $socket :param;

use Future::Buffer;
use Future::IO;
use HTTP::Request;
use HTTP::Response;

use Conduit::Metrics;

field $readbuf;
ADJUST {
   $readbuf = Future::Buffer->new(
      fill => sub () { Future::IO->sysread( $socket, 8192 ); },
   );
}

field $server :param :inheritable;
ADJUST { builtin::weaken( $server ); }

async method read_request ()
{
   defined( my $header = await $readbuf->read_until( qr/\x0D\x0A\x0D\x0A/ ) )
      or return undef;

   my $req = HTTP::Request->parse( $header );

   my $content_length = $req->content_length // 0;

   if( $content_length ) {
      my $body = await $readbuf->read_exactly( $content_length );

      $req->add_content( $body );
   }

   Conduit::Metrics->received_request( $req );
   return $req;
}

field $bytes_written :inheritable;

async method write ( $str )
{
   await Future::IO->write_exactly( $socket, $str );
   $bytes_written += length $str;
}

class Conduit::Client::_ForHTTP
   :strict(params);
inherit Conduit::Client qw( $server $bytes_written );

no if $^V lt v5.40, warnings => "experimental::try", "experimental::builtin";

field $responder :param;

async method run ()
{
   while( defined( my $req = await $self->read_request ) ) {
      my $resp;
      try {
         $resp = await $responder->( $req );
      }
      catch( $e ) {
         chomp $e;
         $resp = HTTP::Response->new( 500, undef,
            [ "Content-Type" => "text/plain" ],
            $e,
         );
      }
      $resp->request( $req );

      $resp->protocol or $resp->protocol( $req->protocol );
      $resp->content_length or $resp->content_length( length $resp->content );

      $bytes_written = 0;

      $server->on_response_header( $req, $resp )
         if $server->can( "on_response_header" );



( run in 1.066 second using v1.01-cache-2.11-cpan-39bf76dae61 )