.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.32 .\" .\" Standard preamble: .\" ======================================================================== .de Sh \" Subsection heading .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. | will give a .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' .\" expand to `' in nroff, nothing in troff, for use with C<>. .tr \(*W-|\(bv\*(Tr .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' 'br\} .\" .\" If the F register is turned on, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . nr % 0 . rr F .\} .\" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .hy 0 .if n .na .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "Server 3" .TH Server 3 "2013-05-02" "perl v5.8.8" "User Contributed Perl Documentation" .SH "NAME" POEx::HTTP::Server \- POE HTTP server .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use POEx::HTTP::Server; .Ve .PP .Vb 10 \& POEx::HTTP::Server->spawn( \& inet => { \& LocalPort => 80 \& }, \& handlers => [ \& '^/$' => 'poe:my-alias/root', \& '^/static' => 'poe:my-alias/static', \& '' => 'poe:my-alias/error' \& ] \& ); .Ve .PP .Vb 7 \& # events of session my-alias: \& sub root { \& my( $heap, $req, $resp ) = @_[HEAP,ARG0,ARG1]; \& $resp->content_type( 'text/html' ); \& $resp->content( generate_html() ); \& $resp->done; \& } .Ve .PP .Vb 5 \& sub static { \& my( $heap, $req, $resp ) = @_[HEAP,ARG0,ARG1]; \& my $file = File::Spec->catfile( $heap->{root}, $req->path ); \& $resp->sendfile( $file ); \& } .Ve .PP .Vb 4 \& sub error { \& my( $heap, $req, resp ) = @_[HEAP,ARG0,ARG1]; \& $resp->error( 404, "Nothing to do for ".$req->path ); \& } .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" POEx::HTTP::Server is a clean \s-1POE\s0 implementation of an \s-1HTTP\s0 server. It uses POEx::URI to simplify event specification. It allows limiting connection concurrency and implements \s-1HTTP\s0 1.1 keep\-alive. It has built-in compatibility with POE::Component::Daemon \*(L"prefork\*(R" servers. .PP POEx::HTTP::Server also includes a method for easily sending a static file to the browser, with automatic support for \f(CW\*(C`HEAD\*(C'\fR and \f(CW\*(C`If\-Modified\-Since\*(C'\fR. .PP POEx::HTTP::Server enforces some of the \s-1HTTP\s0 1.1 requirements, such as the \f(CW\*(C`Content\-Length\*(C'\fR and \f(CW\*(C`Date\*(C'\fR headers. .PP POEx::HTTP::Server differs from POE::Component::Server::HTTP by having a cleaner code base and by being actively maintained. .PP POEx::HTTP::Server differs from POE::Component::Server::SimpleHTTP by not using Moose and not using the YELLING-STYLE of parameter passing. .SH "METHODS" .IX Header "METHODS" POEx::HTTP::Server has one public class method. .Sh "spawn" .IX Subsection "spawn" .Vb 1 \& POEx::HTTP::Server->spawn( %CONFIG ); .Ve .PP Spawns the server session. \f(CW%CONFIG\fR contains one or more of the following parameters: .PP \fIinet\fR .IX Subsection "inet" .PP .Vb 1 \& POEx::HTTP::Server->spawn( inet => $HASHREF ); .Ve .PP Specify the parameters handed to POE::Wheel::SocketFactory when creating the listening socket. .PP As a convenience, \f(CW\*(C`LocalAddr\*(C'\fR is changed into \f(CW\*(C`BindAddr\*(C'\fR and \&\f(CW\*(C`LocalPort\*(C'\fR into \f(CW\*(C`BindPort\*(C'\fR. .PP Defaults to: .PP .Vb 1 \& POEx::HTTP::Server->spawn( inet => { Listen=>1, BindPort=> 80 } ); .Ve .PP \fIhandlers\fR .IX Subsection "handlers" .PP .Vb 2 \& POEx::HTTP::Server->spawn( handlers => $HASHREF ); \& POEx::HTTP::Server->spawn( handlers => $ARRAYREF ); .Ve .PP Set the events that handle a request. Keys to \f(CW$HASHREF\fR are regexes which match on all or part of the request path. Values are poe: urls to the events that will handle the request. .PP The regexes are not anchored. This means that \f(CW\*(C`/foo\*(C'\fR will match the path \&\f(CW\*(C`/something/foo\*(C'\fR. Use \f(CW\*(C`^\*(C'\fR if that's what you mean; \f(CW\*(C`^/foo\*(C'\fR. .PP Specifiying an \f(CW$ARRAYREF\fR allows you to control the order in which the regexes are matched: .PP .Vb 5 \& POEx::HTTP::Server->spawn( handlers => [ \& 'foo' => 'poe:my-session/foo', \& 'onk' => 'poe:my-session/onk', \& 'honk' => 'poe:my-session/honk', \& ] ); .Ve .PP The handler for \f(CW\*(C`onk\*(C'\fR will always match before \f(CW\*(C`honk\*(C'\fR can. .PP Use \f(CW\(aq\(aq\fR if you want a catchall handler. .PP See \*(L"\s-1HANDLERS\s0\*(R" below. .PP \fIhandler\fR .IX Subsection "handler" .PP .Vb 1 \& POEx::HTTP::Server->spawn( handler => $uri ); .Ve .PP Syntatic sugar for .PP .Vb 1 \& POEx::HTTP::Server->spawn( handlers => [ '' => $uri ] ); .Ve .PP \fIalias\fR .IX Subsection "alias" .PP .Vb 1 \& POEx::HTTP::Server->spawn( alias => $ALIAS ); .Ve .PP Sets the server session's alias. The alias defaults to 'HTTPd'. .PP \fIblocksize\fR .IX Subsection "blocksize" .PP .Vb 1 \& POEx::HTTP::Server->spawn( blocksize => 5*$MTU ); .Ve .PP Sets the block size used when sending a file to the browser. See \&\*(L"sendfile\*(R" in POEx::HTTP::Server::Response. See the \*(L"Note about \s-1MTU\s0\*(R". .PP Default value is 7500 octets, or 5 ethernet fames, assuming the standard ethernet \s-1MTU\s0 of 1500 octets. This is useful for Interanet servers, or talking to a reverse proxy on the same \s-1LAN\s0. .PP \fIconcurrency\fR .IX Subsection "concurrency" .PP .Vb 1 \& POEx::HTTP::Server->spawn( concurrency => $NUM ); .Ve .PP Sets the request concurrency level; this is the number of connections that are allowed in parallel. Set to 1 if you want zero concurrency, that is only one connection at a time. .PP Be aware that by activating \*(L"keepalive\*(R", a connection may last for many seconds. If concurrency is low, this will severly limit the availability of the server. If only want one request to be handled at a time, either turn set keepalive off or use \*(L"prefork\*(R". .PP Defaults to (\-1), unlimited concurrency. .PP \fIheaders\fR .IX Subsection "headers" .PP .Vb 1 \& POEx::HTTP::Server->spawn( headers => $HASHREF ); .Ve .PP All the key/value pairs in \f(CW$HASHREF\fR will be set as \s-1HTTP\s0 headers on all responses. .PP By default, the \f(CW\*(C`Server\*(C'\fR header is set to \f(CW\*(C`$PACKAGE/$VERSION\*(C'\fR where \&\f(CW$PACKAGE\fR is \f(CW\*(C`POEx::HTTP::Server\*(C'\fR or any sub-class you might have crated and \f(CW$VERSION\fR is the current version of \f(CW\*(C`POEx::HTTP::Server\*(C'\fR. .PP \fIkeepalive\fR .IX Subsection "keepalive" .PP .Vb 1 \& POEx::HTTP::Server->spawn( keepalive => $N ); .Ve .PP Activates the \s-1HTTP/1\s0.1 persistent connection feature if true. Deactivates keep-alive if false. .PP Default is 0 (off). .PP If \f(CW$N\fR is a number, then it is used as the maximum number of requests per connection. .PP If \f(CW$N\fR isn't a number, or is simply \f(CW1\fR, then the default is 100. .PP \&\fBNote\fR that \s-1HTTP/1\s0.0 Keep-Alive extension is currently not supported. .PP \fIkeepalivetimeout\fR .IX Subsection "keepalivetimeout" .PP .Vb 1 \& POEx::HTTP::Server->spawn( keepalivetimeout => $TIME ); .Ve .PP Sets the number of seconds to wait for a request before closing a connection. This aplies to the time between completing a request and receiving a new one. .PP Defaults to 5 seconds. .PP \fIoptions\fR .IX Subsection "options" .PP .Vb 1 \& POEx::HTTP::Server->spawn( options => $HASHREF ); .Ve .PP Options passed POE::Session\->create. .PP \fIprefork\fR .IX Subsection "prefork" .PP .Vb 1 \& POEx::HTTP::Server->spawn( prefork => 1 ); .Ve .PP Turns on POE::Component::Daemon prefork server support. You must spawn and configure the POE::Component::Daemon yourself. .PP Defaults to 0, no preforking support. .PP In a normal preforking server, only one request will be handled by a child process at the same time. This is equivalent to \*(L"concurrency\*(R" = 1. However, you may set concurrecy to another value, so that each child process may handle several request at the same time. This has not been tested. .PP \fIretry\fR .IX Subsection "retry" .PP .Vb 1 \& POEx::HTTP::Server->spawn( retry => $SECONDS ); .Ve .PP If binding to the port fails, the server will wait \f(CW$SECONDS\fR to retry the operation. .PP Defaults to 60. Use 0 to turn retry off. .PP \fItimeout\fR .IX Subsection "timeout" .PP .Vb 1 \& POEx::HTTP::Server->spawn( timeout => $SECONDS ); .Ve .PP Set the number of seconds to wait for the next \s-1TCP\s0 event. This timeout is used in the following circumstances : .IP "\(bu" 4 between accepting a connection and receiving the full request; .IP "\(bu" 4 between sending a response and flushing the output buffer; .IP "\(bu" 4 while waiting for a streamed response chunk to flush. .PP Defaults to 300 seconds. Setting this timeout to 0 will allow the client to hold a connection open indefinately. .SH "HANDLERS" .IX Header "HANDLERS" A handler is a \s-1POE\s0 event that processes a given \s-1HTTP\s0 request and generates the response. It is invoked with: .ie n .IP """ARG0"" : a POEx::HTTP::Server::Request object." 4 .el .IP "\f(CWARG0\fR : a POEx::HTTP::Server::Request object." 4 .IX Item "ARG0 : a POEx::HTTP::Server::Request object." .PD 0 .ie n .IP """ARG1"" : a POEx::HTTP::Server::Response object." 4 .el .IP "\f(CWARG1\fR : a POEx::HTTP::Server::Response object." 4 .IX Item "ARG1 : a POEx::HTTP::Server::Response object." .PD .PP The handler should query the request object for details or parameters of the request. .PP .Vb 2 \& my $req = $_[ARG0]; \& my $file = File::Spec->catfile( $doc_root, $req->uri->path ); .Ve .PP .Vb 1 \& my $query = $req->uri->query_form; .Ve .PP .Vb 3 \& my $conn = $req->connection; \& my $ip = $conn->remote_ip; \& my $port = $conn->remote_port; .Ve .PP The handler must populate the response object with necessary headers and content. If the handler wishes to send an error to the browser, it should set the response code approriately. A default \s-1HTTP\s0 status of \s-1RC_OK\s0 (200) is used. The response is sent to the browser with either \&\f(CW\*(C`\*(L"respond\*(R" in POEx::HTTP::Server::Response\*(C'\fR or \&\f(CW\*(C`\*(L"send\*(R" in POEx::HTTP::Server::Response\*(C'\fR. When the handler is finished, it must call \f(CW\*(C`\*(L"done\*(R" in POEx::HTTP::Server::Response\*(C'\fR on the response object. .PP .Vb 6 \& # Generated content \& my $resp = $_[ARG1]; \& $resp->content_type( 'text/plain' ); \& $resp->content( "Hello world\en" ); \& $resp->respond; \& $resp->done; .Ve .PP .Vb 6 \& # HTTP redirect \& use HTTP::Status; \& $resp->code( RC_FOUND ); \& $resp->header( 'Location' => $new_uri ); \& $resp->respond; \& $resp->done; .Ve .PP .Vb 7 \& # Static file \& $resp->content_type( 'text/plain' ); \& my $io = IO::File->new( $file ); \& while( <$io> ) { \& $resp->send( $_ ); \& } \& $resp->done; .Ve .PP The last example is silly. It would be better to use \*(L"sendfile\*(R" like so: .PP .Vb 3 \& $resp->content_type( 'image/gif' ); \& $resp->sendfile( $file ); \& # Don't call ->done after sendfile .Ve .PP Handlers may chain to other event handlers, using normal \s-1POE\s0 events. You must keep track of at least the response handler so that you may call \f(CW\*(C`done\*(C'\fR when the request is finished. .PP Here is an example of an unrolled loop: .PP .Vb 5 \& sub handler { \& my( $heap, $resp ) = $_[HEAP,ARG1]; \& $heap->{todo} = [ qw( one two three ) ]; \& $poe_kernel->yield( next_handler => $resp ); \& } .Ve .PP .Vb 2 \& sub next_handler { \& my( $heap, $resp ) = $_[HEAP,ARG0]; .Ve .PP .Vb 3 \& # Get the request object from the response \& my $req = $resp->request; \& # And you can get the connection object from the request .Ve .PP .Vb 11 \& my $h = shift @{ $heap->{todo} }; \& if( $h ) { \& # Send the content returned by event handlers in another session \& my $chunk = $poe_kernel->call( $heap->{session}, $h, $req ) \& $resp->send( $chunk ); \& $poe_kernel->yield( next_handler => $resp ); \& } \& else { \& $poe_kernel->yield( 'last_handler', $resp ); \& } \& } .Ve .PP .Vb 4 \& sub last_handler { \& my( $heap, $resp ) = $_[HEAP,ARG0]; \& $resp->done; \& } .Ve .PP .Vb 5 \& # Event handlers in the other session: \& sub one { \& # .... \& return $chunk; \& } .Ve .PP .Vb 4 \& sub two { \& # .... \& return $chunk; \& } .Ve .PP .Vb 4 \& sub three { \& # .... \& return $chunk; \& } .Ve .Sh "Handler parameters" .IX Subsection "Handler parameters" \&\s-1POE\s0 URIs are allowed to have their own parameter. If you use them, they will appear as a hashref in \f(CW\*(C`ARG0\*(C'\fR with the request and response objects as \&\f(CW\*(C`ARG1\*(C'\fR and \f(CW\*(C`ARG2\*(C'\fR respectively. .PP .Vb 1 \& POEx::HTTP::Server->spawn( handler => 'poe:my-session/handler?honk=bonk' ); .Ve .PP .Vb 4 \& sub handler { \& my( $args, $req, $resp ) = @_[ARG0, ARG1, ARG2]; \& # $args = { honk => 'bonk' } \& } .Ve .Sh "Handler exceptions" .IX Subsection "Handler exceptions" Request handler invocations are wrapped in \f(CW\*(C`eval{}\*(C'\fR. If the handler throws an exception with \f(CW\*(C`die\*(C'\fR this will be reported to the browser as a short message. Obviously this only applies to the initial request handler. If you yield to other \s-1POE\s0 event handlers, they will not report exceptions to the browser. .Sh "Special handlers" .IX Subsection "Special handlers" There are 5 special handlers that are invoked when a browser connection is opened and closed, before and after each request and when an error occurs. .PP The note about \*(L"Handler parameters\*(R" also aplies to special handlers. .PP \fIon_connect\fR .IX Subsection "on_connect" .PP Invoked when a new connection is made to the server. \f(CW\*(C`ARG0\*(C'\fR is a POEx::HTTP::Server::Connection object that may be queried for information about the connection. This connection object will be shared by all requests objects that use this connection. .PP .Vb 7 \& POEx::HTTP::Server->spawn( \& handlers => { on_connect => 'poe:my-session/on_connect' } \& ); \& sub on_connect { \& my( $object, $connection ) = @_[OBJECT, ARG0]; \& # ... \& } .Ve .PP \fIon_disconnect\fR .IX Subsection "on_disconnect" .PP Invoked when a connection is closed. \f(CW\*(C`ARG0\*(C'\fR is the same POEx::HTTP::Server::Connection object that was passed to \*(L"on_connect\*(R". .PP \fIpre_request\fR .IX Subsection "pre_request" .PP Invoked after a request is read from the browser but before it is processed. \&\f(CW\*(C`ARG0\*(C'\fR is a POEx::HTTP::Server::Request object. There is no \f(CW\*(C`ARG1\*(C'\fR. .PP .Vb 8 \& POEx::HTTP::Server->spawn( \& handlers => { pre_request => 'poe:my-session/pre' } \& ); \& sub pre { \& my( $object, $request ) = @_[OBJECT, ARG0]; \& my $connection = $request->connection; \& # ... \& } .Ve .PP If you use \*(L"keepalive\*(R", \*(L"pre_request\*(R" will be invoked more often then \&\f(CW\*(C`on_connect\*(C'\fR. .PP \fIpost_request\fR .IX Subsection "post_request" .PP Invoked after a response has been sent to the browser. \&\f(CW\*(C`ARG0\*(C'\fR is a POEx::HTTP::Server::Request object. \&\f(CW\*(C`ARG1\*(C'\fR is a POEx::HTTP::Server::Response object, with it's \f(CW\*(C`content\*(C'\fR cleared. .PP .Vb 8 \& POEx::HTTP::Server->spawn( \& handlers => { pre_request => 'poe:my-session/post' } \& ); \& sub post { \& my( $self, $request, $response ) = @_[OBJECT, ARG0, ARG1]; \& my $connection = $request->connection; \& # ... \& } .Ve .PP \fIstream_request\fR .IX Subsection "stream_request" .PP Invoked when a chunk has been flushed to the \s-1OS\s0, if you are streaming a response to the browser. Streaming is turned on with \&\*(L"streaming\*(R" in POEx::HTTP::Server::Response. .PP Please remember that while a chunk might be flushed, the \s-1OS\s0's network layer might still decide to combine several chunks into a single packet. And this even though we setup a \fIhot\fR socket with \f(CW\*(C`TCP_NODELAY\*(C'\fR set to 1 and \&\f(CW\*(C`SO_SNDBUF\*(C'\fR to 576. .PP \fIon_error\fR .IX Subsection "on_error" .PP Invoked when the server detects an error. \f(CW\*(C`ARG0\*(C'\fR is a POEx::HTTP::Server::Error object. .PP There are 2 types of errors: network errors and \s-1HTTP\s0 errors. They may be distiguished by calling the error object's \f(CW\*(C`op\*(C'\fR method. If \f(CW\*(C`op\*(C'\fR returns \&\f(CW\*(C`undef()\*(C'\fR, it is an \s-1HTTP\s0 error, otherwise a network error. \s-1HTTP\s0 errors already have a message to the browser with \s-1HTML\s0 content. You may modify the \&\s-1HTTP\s0 error's content and headers before they get sent back to the browser. .PP Unlike \s-1HTTP\s0 errors, network errors are never sent to the browser. .PP .Vb 16 \& POEx::HTTP::Server->spawn( \& handlers => { on_error => 'poe:my-session/error' } \& ); \& sub error { \& my( $self, $err ) = @_[OBJECT, ARG0]; \& if( $err->op ) { # network error \& $self->LOG( $err->op." error [".$err->errnum, "] ".$err->errstr ); \& # or the equivalent \& $self->LOG( $err->content ); \& } \& else { # HTTP error \& $self->LOG( $err->status_line ); \& $self->content_type( 'text/plain' ); \& $self->content( "Don't do that!" ); \& } \& } .Ve .SH "EVENTS" .IX Header "EVENTS" The following \s-1POE\s0 events may be used to control POEx::HTTP::Server. .Sh "shutdown" .IX Subsection "shutdown" .Vb 2 \& $poe_kernel->signal( $poe_kernel => 'shutdown' ); \& $poe_kernel->post( HTTPd => 'shutdown' ); .Ve .PP Initiate server shutdown. Any pending requests will stay active, however. The session will exit when the last of the requests has finished. No further requests will be accepted, even if keepalive is in use. .Sh "handlers_get" .IX Subsection "handlers_get" .Vb 1 \& my $handlers = $poe_kernel->call( HTTPd => 'handlers_get' ); .Ve .PP Fetch a hashref of handlers and their URIs. This list contains both the special handlers and the \s-1HTTP\s0 handlers. .Sh "handlers_set" .IX Subsection "handlers_set" .Vb 3 \& $poe_kernel->post( HTTPD => handlers_set => $URI ); \& $poe_kernel->post( HTTPD => handlers_set => $ARRAYREF ); \& $poe_kernel->post( HTTPD => handlers_set => $HASHREF ); .Ve .PP Change all the handlers at once. The sole parameter is the same as \*(L"handlers\*(R" passed to \*(L"spawn\*(R". .PP Note that modifying the set of handlers will only modify the handlers for new connections, not currently open connections. .Sh "handlers_add" .IX Subsection "handlers_add" .Vb 3 \& $poe_kernel->post( HTTPD => handlers_add => $URI ); \& $poe_kernel->post( HTTPD => handlers_add => $ARRAYREF ); \& $poe_kernel->post( HTTPD => handlers_add => $HASHREF ); .Ve .PP Add new handlers to the server, overriding any that might already exist. The ordering of handlers is preserved, with all new handlers added to the end of the list. The sole parameter is the same as \*(L"handlers\*(R" passed to \*(L"spawn\*(R". .PP Note that modifying the set of handlers will only modify the handlers for new connections, not currently open connections. .Sh "handlers_remove" .IX Subsection "handlers_remove" .Vb 3 \& $poe_kernel->post( HTTPD => handlers_remove => $RE ); \& $poe_kernel->post( HTTPD => handlers_remove => $ARRAYREF ); \& $poe_kernel->post( HTTPD => handlers_remove => $HASHREF ); .Ve .PP Remove one or more handlers from the server. The handlers are removed based on the regex, not the handler's \s-1URI\s0. The regex must be exactly identical to the regex supplied to \*(L"handlers\*(R". .PP The sole parameter may be : .PP \fI$RE\fR .IX Subsection "$RE" .PP .Vb 1 \& $poe_kernel->post( HTTPD => handers_remove => '^/static' ); .Ve .PP The handler associated with this regex is removed. .PP \fI$ARRAYREF\fR .IX Subsection "$ARRAYREF" .PP .Vb 2 \& $poe_kernel->post( HTTPD => handers_remove => \& [ '^/static', '^/static/bigger' ] ); .Ve .PP Remove a list of handlers associated. .PP \fI$HASHREF\fR .IX Subsection "$HASHREF" .PP .Vb 2 \& $poe_kernel->post( HTTPD => handers_remove => \& { '^/static' => 1, '^/static/bigger' => 1 } ); .Ve .PP The hash's keys are a list of regexes to remove. The values are ignored. .PP Note that modifying the set of handlers will not modify the handlers for currently open connections. .SH "NOTES" .IX Header "NOTES" .Sh "Sending headers" .IX Subsection "Sending headers" If you wish to send the headers right away, but send the body later, you may do: .PP .Vb 2 \& $resp->header( 'Content-Length' => $size ); \& $resp->send; .Ve .PP The above causes the headers to be sent, allong with any content you might have added to \f(CW$resp\fR. .PP When you want to send the body: .PP .Vb 1 \& $resp->send( $content ); .Ve .PP When you are finished: .PP .Vb 1 \& $resp->done; .Ve .Sh "Streaming" .IX Subsection "Streaming" Streaming is very similar to sending the headers and body seperately. See above. One difference is that the headers will be flushed and the socket will be set to \fIhot\fR with \s-1TCP_NODELAY\s0 and \s-1SO_SNBUF\s0. Another difference is that keepalive is deactivated for the connection. Finally difference is that you will see \f(CW\*(C`\*(L"stream_request\*(R"\*(C'\fR when you are allowed to send the next block. Look for \f(CW\*(C`\*(L"post_request\*(R"\*(C'\fR to find out when the last block has been sent to the browser. .PP .Vb 3 \& $resp->streaming( 1 ); \& $resp->header( 'Content-Length' => $size ); \& $resp->send; .Ve .PP When you want to send a chunk: .PP .Vb 1 \& $resp->send( $chunk ); .Ve .PP This can be repeated as long as you want. .PP When you are finished: .PP .Vb 1 \& $resp->done; .Ve .PP This will provoke a \*(L"post_request\*(R" when the last chunk is flushed. .Sh "blocksize and \s-1MTU\s0" .IX Subsection "blocksize and MTU" If you are using sendfile, but do not have Sys::Sendfile installed you really should set \*(L"blocksize\*(R" to a whole multiple of the interface's \s-1MTU\s0. Doing so automatically is currently beyond the scope of this module. Please see \*(L"mtu\*(R" in Net::Interface. But that won't help for servers available over the the Internet; your local ethernet interface's \s-1MTU\s0 (1500) is probably greater then your internet connection's \s-1MTU\s0 (1400\-1492 for \s-1DSL\s0). What's more, the \s-1MTU\s0 could be as low as 576. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\s-1POE\s0, POEx::HTTP::Server::Request, POEx::HTTP::Server::Response, POEx::HTTP::Server::Error, POEx::HTTP::Server::Connection, .SH "AUTHOR" .IX Header "AUTHOR" Philip Gwyn, .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright (C) 2010, 2011 by Philip Gwyn. All rights reserved. .PP This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.