.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.40) .\" .\" Standard preamble: .\" ======================================================================== .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. \*(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- .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" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Feersum 3pm" .TH Feersum 3pm "2020-12-09" "perl v5.32.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Feersum \- A PSGI engine for Perl based on EV/libev .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 3 \& use Feersum; \& my $ngn = Feersum\->endjinn; # singleton \& $ngn\->use_socket($io_socket); \& \& # register a PSGI handler \& $ngn\->psgi_request_handler(sub { \& my $env = shift; \& return [200, \& [\*(AqContent\-Type\*(Aq=>\*(Aqtext/plain\*(Aq], \& ["You win one cryptosphere!\en"]]; \& }); \& \& # register a Feersum handler: \& $ngn\->request_handler(sub { \& my $req = shift; \& my $t; $t = EV::timer 2, 0, sub { \& $req\->send_response( \& 200, \& [\*(AqContent\-Type\*(Aq => \*(Aqtext/plain\*(Aq], \& \e"You win one cryptosphere!\en" \& ); \& undef $t; \& }; \& }); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Feersum is an \s-1HTTP\s0 server built on \s-1EV\s0. It fully supports the \s-1PSGI 1.03\s0 spec including the \f(CW\*(C`psgi.streaming\*(C'\fR interface and is compatible with Plack. \&\s-1PSGI 1.1,\s0 which has yet to be published formally, is also supported. Feersum also has its own \*(L"native\*(R" interface which is similar in a lot of ways to \s-1PSGI,\s0 but is \fBnot compatible\fR with \s-1PSGI\s0 or \s-1PSGI\s0 middleware. .PP Feersum uses a single-threaded, event-based programming architecture to scale and can handle many concurrent connections efficiently in both \s-1CPU\s0 and \s-1RAM.\s0 It skips doing a lot of sanity checking with the assumption that a \*(L"front-end\*(R" \&\s-1HTTP/HTTPS\s0 server is placed between it and the Internet. .SS "How It Works" .IX Subsection "How It Works" All of the request-parsing and I/O marshalling is done using C or \s-1XS\s0 code. \&\s-1HTTP\s0 parsing is done by picohttpparser, which is the core of HTTP::Parser::XS. The network I/O is done via the libev library. This is made possible by \f(CW\*(C`EV::MakeMaker\*(C'\fR, which allows extension writers to link against the same libev that \f(CW\*(C`EV\*(C'\fR is using. This means that one can write an evented app using \f(CW\*(C`EV\*(C'\fR or AnyEvent from Perl that completely co-operates with the server's event loop. .PP Since the Perl \*(L"app\*(R" (handler) is executed in the same thread as the event loop, one need to be careful to not block this thread. Standard techniques include using AnyEvent or \s-1EV\s0 idle and timer watchers, using Coro to multitask, and using sub-processes to do heavy lifting (e.g. AnyEvent::Worker and AnyEvent::DBI). .PP Feersum also attempts to do as little copying of data as possible. Feersum uses the low-level \f(CW\*(C`writev\*(C'\fR system call to avoid having to copy data into a buffer. For response data, references to scalars are kept in order to avoid copying the string values (once the data is written to the socket, the reference is dropped and the data is garbage collected). .PP A trivial hello-world handler can process in excess of 5000 requests per second on a 4\-core Intel(R) Xeon(R) E5335 @ 2.00GHz using TCPv4 on the loopback interface, \s-1OS\s0 Ubuntu 6.06LTS, Perl 5.8.7. Your mileage will likely vary. .PP For even faster results, Feersum can support very simple pre-forking (See feersum, Feersum::Runner or Plack::Handler::Feersum for details). .SH "INTERFACE" .IX Header "INTERFACE" There are two handler interfaces for Feersum: The \s-1PSGI\s0 handler interface and the \*(L"Feersum-native\*(R" handler interface. The \s-1PSGI\s0 handler interface is fully \&\s-1PSGI 1.03\s0 compatible and supports \f(CW\*(C`psgi.streaming\*(C'\fR. The \&\f(CW\*(C`psgix.input.buffered\*(C'\fR and \f(CW\*(C`psgix.io\*(C'\fR features of \s-1PSGI 1.1\s0 are also supported. The Feersum-native handler interface is \*(L"inspired by\*(R" \s-1PSGI,\s0 but does some things differently for speed. .PP Feersum will use \*(L"Transfer-Encoding: chunked\*(R" for \s-1HTTP/1.1\s0 clients and \&\*(L"Connection: close\*(R" streaming as a fallback. Technically \*(L"Connection: close\*(R" streaming isn't part of the \s-1HTTP/1.0\s0 or 1.1 spec, but many browsers and agents support it anyway. .PP Currently \s-1POST/PUT\s0 does not stream input, but \fBread()\fR can be called on \&\f(CW\*(C`psgi.input\*(C'\fR to get the body (which has been buffered up before the request callback is called and therefore will never block). Likely \f(CW\*(C`read()\*(C'\fR will change to raise \s-1EAGAIN\s0 responses and allow for a callback to be registered on the arrival of more data. (The \f(CW\*(C`psgix.input.buffered\*(C'\fR env var is set to reflect this). .SS "\s-1PSGI\s0 interface" .IX Subsection "PSGI interface" Feersum fully supports the \s-1PSGI 1.03\s0 spec including \f(CW\*(C`psgi.streaming\*(C'\fR. .PP See also Plack::Handler::Feersum, which provides a way to use Feersum with plackup and Plack::Runner. .PP Call \f(CW\*(C`psgi_request_handler($app)\*(C'\fR to register \f(CW$app\fR as a \s-1PSGI\s0 handler. .PP .Vb 2 \& my $app = do $filename; \& Feersum\->endjinn\->psgi_request_handler($app); .Ve .PP The env hash passed in will always have the following keys in addition to dynamic ones: .PP .Vb 7 \& psgi.version => [1,0], \& psgi.nonblocking => 1, \& psgi.multithread => \*(Aq\*(Aq, # i.e. false \& psgi.multiprocess => \*(Aq\*(Aq, \& psgi.streaming => 1, \& psgi.errors => \e*STDERR, \& SCRIPT_NAME => "", .Ve .PP Feersum adds these extensions (see below for info) .PP .Vb 5 \& psgix.input.buffered => 1, \& psgix.output.buffered => 1, \& psgix.body.scalar_refs => 1, \& psgix.output.guard => 1, \& psgix.io => \e$magical_io_socket, .Ve .PP Note that \s-1SCRIPT_NAME\s0 is always blank (but defined). \s-1PATH_INFO\s0 will contain the path part of the requested \s-1URI.\s0 .PP For requests with a body (e.g. \s-1POST\s0) \f(CW\*(C`psgi.input\*(C'\fR will contain a valid file-handle. Feersum currently passes \f(CW\*(C`undef\*(C'\fR for psgi.input when there is no body to avoid unnecessary work. .PP .Vb 4 \& my $r = delete $env\->{\*(Aqpsgi.input\*(Aq}; \& $r\->read($body, $env\->{CONTENT_LENGTH}); \& # optional: choose to stop receiving further input, discard buffers: \& $r\->close(); .Ve .PP The \f(CW\*(C`psgi.streaming\*(C'\fR interface is fully supported, including the writer-object \f(CW\*(C`poll_cb\*(C'\fR callback feature defined in \s-1PSGI 1.03.\s0 \fBNote that poll_cb is removed from the preliminary \s-1PSGI 1.1\s0 spec\fR. Feersum calls the poll_cb callback after all data has been flushed out and the socket is write-ready. The data is buffered until the callback returns at which point it will be immediately flushed to the socket. .PP .Vb 10 \& my $app = sub { \& my $env = shift; \& return sub { \& my $respond = shift; \& my $w = $respond\->([ \& 200, [\*(AqContent\-Type\*(Aq => \*(Aqapplication/json\*(Aq] \& ]); \& my $n = 0; \& $w\->poll_cb(sub { \& $_[0]\->write(get_next_chunk()); \& # will also unset the poll_cb: \& $_[0]\->close if ($n++ >= 100); \& }); \& }; \& }; .Ve .PP Note that \f(CW\*(C`$w\->close()\*(C'\fR will be called when the last reference to the writer is dropped. .SS "\s-1PSGI\s0 extensions" .IX Subsection "PSGI extensions" .IP "psgix.body.scalar_refs" 4 .IX Item "psgix.body.scalar_refs" Scalar refs in the response body are supported, and is indicated as an via the \&\fBpsgix.body.scalar_refs\fR env variable. Passing by reference is \&\fBsignificantly\fR faster than copying a value onto the return stack or into an array. It's also very useful when broadcasting a message to many connected clients. This is a Feersum-native feature exposed to \s-1PSGI\s0 apps; very few other \s-1PSGI\s0 handlers will support this. .IP "psgix.output.buffered" 4 .IX Item "psgix.output.buffered" Calls to \f(CW\*(C`$w\->write()\*(C'\fR will never block. This behaviour is indicated by \&\fBpsgix.output.buffered\fR in the \s-1PSGI\s0 env hash. .IP "psgix.input.buffered" 4 .IX Item "psgix.input.buffered" \&\f(CW\*(C`psgix.input.buffered\*(C'\fR is defined as part of \s-1PSGI 1.1.\s0 It means that calls to read on the input handle will never block because the complete input has been buffered in some way. .Sp Feersum currently buffers the entire input in memory calling the callback. .Sp \&\fBFeersum's input behaviour \s-1MAY\s0 eventually change to not be psgix.input.buffered!\fR Likely, a \f(CW\*(C`poll_cb()\*(C'\fR method similar to how the writer handle works could be registered to have input \*(L"pushed\*(R" to the app. .IP "psgix.output.guard" 4 .IX Item "psgix.output.guard" The streaming responder has a \f(CW\*(C`response_guard()\*(C'\fR method that can be used to attach a guard to the request. When the request completes (all data has been written to the socket and the socket has been closed) the guard will trigger. This is an alternate means to doing a \*(L"write completion\*(R" callback via \&\f(CW\*(C`poll_cb()\*(C'\fR that should be more efficient. An analogy is the \*(L"on_drain\*(R" handler in AnyEvent::Handle. .Sp A \*(L"guard\*(R" in this context is some object that will do something interesting in its \s-1DESTROY/DEMOLISH\s0 method. For example, Guard. .IP "psgix.io" 4 .IX Item "psgix.io" The raw socket extension \fBpsgix.io\fR is provided in order to support Web::Hippie and websockets. \f(CW\*(C`psgix.io\*(C'\fR is defined as part of \s-1PSGI 1.1.\s0 To obtain the IO::Socket corresponding to this connection, read this environment variable. .Sp The underlying file descriptor will have \f(CW\*(C`O_NONBLOCK\*(C'\fR, \f(CW\*(C`TCP_NODELAY\*(C'\fR, \&\f(CW\*(C`SO_OOBINLINE\*(C'\fR enabled and \f(CW\*(C`SO_LINGER\*(C'\fR disabled. .Sp \&\s-1PSGI\s0 apps \fB\s-1MUST\s0\fR use a \f(CW\*(C`psgi.streaming\*(C'\fR response so that Feersum doesn't try to flush and close the connection. Additionally, the \*(L"respond\*(R" parameter to the streaming callback \fB\s-1MUST NOT\s0\fR be called for the same reason. .Sp .Vb 5 \& my $env = shift; \& return sub { \& my $fh = $env\->{\*(Aqpsgix.io\*(Aq}; \& syswrite $fh, \& }; .Ve .SS "The Feersum-native interface" .IX Subsection "The Feersum-native interface" The Feersum-native interface is inspired by \s-1PSGI,\s0 but is inherently \&\fBincompatible\fR with it. Apps written against this \s-1API\s0 will not work as a \&\s-1PSGI\s0 app. .PP \&\fBThis interface may have removals and is not stable until Feersum reaches version 1.0\fR, at which point the interface \s-1API\s0 will become stable and will only change for bug fixes or new additions. The \*(L"stable\*(R" and will retain backwards compatibility until at least the next major release. .PP The main entry point is a sub-ref passed to \f(CW\*(C`request_handler\*(C'\fR. This sub is passed a reference to an object that represents an \s-1HTTP\s0 connection. Currently the request_handler is called during the \*(L"check\*(R" and \*(L"idle\*(R" phases of the \s-1EV\s0 event loop. The handler is always called after request headers have been read. Currently, the handler will \fBonly\fR be called after a full request entity has been received for POST/PUT/etc. .PP The simplest way to send a response is to use \f(CW\*(C`send_response\*(C'\fR: .PP .Vb 2 \& my $req = shift; \& $req\->send_response(200, \e@headers, ["body ", \e"parts"]); .Ve .PP Or, if the app has everything packed into a single scalar already, just pass it in by reference. .PP .Vb 2 \& my $req = shift; \& $req\->send_response(200, \e@headers, \e"whole body"); .Ve .PP Both of the above will generate \f(CW\*(C`Content\-Length\*(C'\fR header (replacing any that were pre-defined in \f(CW@headers\fR). .PP An environment hash is easy to obtain, but is a method call instead of a parameter to the callback. (In \s-1PSGI,\s0 there is no \f(CW$req\fR object; the env hash is the first parameter to the callback). The hash contains the same items as it would for a \s-1PSGI\s0 handler (see above for those). .PP .Vb 2 \& my $req = shift; \& my $env = $req\->env(); .Ve .PP To read input from a \s-1POST/PUT,\s0 use the \f(CW\*(C`psgi.input\*(C'\fR item of the env hash. .PP .Vb 7 \& if ($req\->{REQUEST_METHOD} eq \*(AqPOST\*(Aq) { \& my $body = \*(Aq\*(Aq; \& my $r = delete $env\->{\*(Aqpsgi.input\*(Aq}; \& $r\->read($body, $env\->{CONTENT_LENGTH}); \& # optional: \& $r\->close(); \& } .Ve .PP Starting a response in stream mode enables the \f(CW\*(C`write()\*(C'\fR method (which really acts more like a buffered 'print'). Calls to \f(CW\*(C`write()\*(C'\fR will never block. .PP .Vb 5 \& my $req = shift; \& my $w = $req\->start_streaming(200, \e@headers); \& $w\->write(\e"this is a reference to some shared chunk\en"); \& $w\->write("regular scalars are OK too\en"); \& $w\->close(); # close off the stream .Ve .PP The writer object supports \f(CW\*(C`poll_cb\*(C'\fR as also specified in \s-1PSGI 1.03.\s0 Feersum will call the callback only when all data has been flushed out at the socket level. Use \f(CW\*(C`close()\*(C'\fR or unset the handler (\f(CW\*(C`$w\->poll_cb(undef)\*(C'\fR) to stop the callback from getting called. .PP .Vb 9 \& my $req = shift; \& my $w = $req\->start_streaming( \& "200 OK", [\*(AqContent\-Type\*(Aq => \*(Aqapplication/json\*(Aq]); \& my $n = 0; \& $w\->poll_cb(sub { \& # $_[0] is a copy of $w so a closure doesn\*(Aqt need to be made \& $_[0]\->write(get_next_chunk()); \& $_[0]\->close if ($n++ >= 100); \& }); .Ve .PP Note that \f(CW\*(C`$w\->close()\*(C'\fR will be called when the last reference to the writer is dropped. .SH "METHODS" .IX Header "METHODS" These are methods on the global Feersum singleton. .ie n .IP """new()""" 4 .el .IP "\f(CWnew()\fR" 4 .IX Item "new()" .PD 0 .ie n .IP """endjinn()""" 4 .el .IP "\f(CWendjinn()\fR" 4 .IX Item "endjinn()" .PD Returns the \f(CW\*(C`Feersum\*(C'\fR singleton. Takes no parameters. .ie n .IP """use_socket($sock)""" 4 .el .IP "\f(CWuse_socket($sock)\fR" 4 .IX Item "use_socket($sock)" Use the file-descriptor attached to a listen-socket to accept connections. .Sp \&\s-1TLS\s0 sockets are \fB\s-1NOT\s0\fR supported nor are they detected. Feersum needs to use the socket at a low level and will ignore any encryption that has been established (data is always sent in the clear). The intented use of Feersum is over localhost-only sockets. .Sp A reference to \f(CW$sock\fR is kept as \f(CW\*(C`Feersum\->endjinn\->{socket}\*(C'\fR. .ie n .IP """accept_on_fd($fileno)""" 4 .el .IP "\f(CWaccept_on_fd($fileno)\fR" 4 .IX Item "accept_on_fd($fileno)" Use the specified fileno to accept connections. May be used as an alternative to \f(CW\*(C`use_socket\*(C'\fR. .ie n .IP """unlisten()""" 4 .el .IP "\f(CWunlisten()\fR" 4 .IX Item "unlisten()" Stop listening to the socket specified by use_socket or accept_on_fd. .ie n .IP """request_handler(sub { my $req = shift; ... })""" 4 .el .IP "\f(CWrequest_handler(sub { my $req = shift; ... })\fR" 4 .IX Item "request_handler(sub { my $req = shift; ... })" Sets the global request handler. Any previous handler is replaced. .Sp The handler callback is passed a Feersum::Connection object. .Sp \&\fBSubject to change\fR: if the request has an entity body then the handler will be called \fBonly\fR after receiving the body in its entirety. The headers *must* specify a Content-Length of the body otherwise the request will be rejected. The maximum size is hard coded to 2147483647 bytes (this may be considered a bug). .ie n .IP """psgi_request_handler(sub { my $env = shift; ... })""" 4 .el .IP "\f(CWpsgi_request_handler(sub { my $env = shift; ... })\fR" 4 .IX Item "psgi_request_handler(sub { my $env = shift; ... })" Like request_handler, but assigns a \s-1PSGI\s0 handler instead. .ie n .IP """read_timeout()""" 4 .el .IP "\f(CWread_timeout()\fR" 4 .IX Item "read_timeout()" .PD 0 .ie n .IP """read_timeout($duration)""" 4 .el .IP "\f(CWread_timeout($duration)\fR" 4 .IX Item "read_timeout($duration)" .PD Get or set the global read timeout. .Sp Feersum will wait about this long to receive all headers of a request (within the tollerances provided by libev). If an entity body is part of the request (e.g. \s-1POST\s0 or \s-1PUT\s0) it will wait this long between successful \f(CW\*(C`read()\*(C'\fR system calls. .ie n .IP """graceful_shutdown(sub { .... })""" 4 .el .IP "\f(CWgraceful_shutdown(sub { .... })\fR" 4 .IX Item "graceful_shutdown(sub { .... })" Causes Feersum to initiate a graceful shutdown of all outstanding connections. No new connections will be accepted. The reference to the socket provided in \fBuse_socket()\fR is kept. .Sp The sub parameter is a completion callback. It will be called when all connections have been flushed and closed. This allows one to do something like this: .Sp .Vb 11 \& my $cv = AE::cv; \& my $death = AE::timer 2.5, 0, sub { \& fail "SHUTDOWN TOOK TOO LONG"; \& exit 1; \& }; \& Feersum\->endjinn\->graceful_shutdown(sub { \& pass "all gracefully shut down, supposedly"; \& undef $death; \& $cv\->send; \& }); \& $cv\->recv; .Ve .ie n .IP """DIED""" 4 .el .IP "\f(CWDIED\fR" 4 .IX Item "DIED" Not really a method so much as a static function. Works similar to \&\s-1EV\s0's/AnyEvent's error handler. .Sp To install a handler: .Sp .Vb 2 \& no strict \*(Aqrefs\*(Aq; \& *{\*(AqFeersum::DIED\*(Aq} = sub { warn "nuts $_[0]" }; .Ve .Sp Will get called for any errors that happen before the request handler callback is called, when the request handler callback throws an exception and potentially for other not-in-a-request-context errors. .Sp It will not get called for read timeouts that occur while waiting for a complete header (and also, until Feersum supports otherwise, time-outs while waiting for a request entity body). .Sp Any exceptions thrown in the handler will generate a warning and not propagated. .ie n .IP """set_server_name_and_port($host,$port)""" 4 .el .IP "\f(CWset_server_name_and_port($host,$port)\fR" 4 .IX Item "set_server_name_and_port($host,$port)" Override Feersum's notion of what \s-1SERVER_HOST\s0 and \s-1SERVER_PORT\s0 should be. .SH "GRITTY DETAILS" .IX Header "GRITTY DETAILS" .SS "Compile Time Options" .IX Subsection "Compile Time Options" There are a number of constants at the top of Feersum.xs. If you change any of these, be sure to note that in any bug reports. .IP "\s-1MAX_HEADERS\s0" 4 .IX Item "MAX_HEADERS" Defaults to 64. Controls how many headers can be present in an \s-1HTTP\s0 request. .Sp If a request exceeds this limit, a 400 response is given and the app handler does not run. .IP "\s-1MAX_HEADER_NAME_LEN\s0" 4 .IX Item "MAX_HEADER_NAME_LEN" Defaults to 128. Controls how long the name of each header can be. .Sp If a request exceeds this limit, a 400 response is given and the app handler does not run. .IP "\s-1MAX_BODY_LEN\s0" 4 .IX Item "MAX_BODY_LEN" Defaults to ~2GB. Controls how large the body of a POST/PUT/etc. can be when that request has a \f(CW\*(C`Content\-Length\*(C'\fR header. .Sp If a request exceeds this limit, a 413 response is given and the app handler does not run. .Sp See also \s-1BUGS\s0 .IP "\s-1READ_BUFSZ\s0" 4 .IX Item "READ_BUFSZ" .PD 0 .IP "\s-1READ_INIT_FACTOR\s0" 4 .IX Item "READ_INIT_FACTOR" .IP "\s-1READ_GROW_FACTOR\s0" 4 .IX Item "READ_GROW_FACTOR" .PD \&\s-1READ_BUFSZ\s0 defaults to 4096, \s-1READ_INIT_FACTOR 2\s0 and \s-1READ_GROW_FACTOR 8.\s0 .Sp Together, these tune how data is read for a request. .Sp Read buffers start out at \s-1READ_INIT_FACTOR\s0 * \s-1READ_BUFSZ\s0 bytes. If another read is needed and the buffer is under \s-1READ_BUFSZ\s0 bytes then the buffer gets an additional \s-1READ_GROW_FACTOR\s0 * \s-1READ_BUFSZ\s0 bytes. The trade-off with the grow factor is memory usage vs. system calls. .IP "\s-1AUTOCORK_WRITES\s0" 4 .IX Item "AUTOCORK_WRITES" Controls how response data is written to sockets. If enabled (the default) the event loop is used to wait until the socket is writable, otherwise a write is performed immediately. In either case, non-blocking writes are used. Using the event loop is \*(L"nicer\*(R" but perhaps introduces latency, hence this option. .IP "\s-1FLASH_SOCKET_POLICY_SUPPORT\s0" 4 .IX Item "FLASH_SOCKET_POLICY_SUPPORT" .PD 0 .IP "\s-1FLASH_SOCKET_POLICY\s0" 4 .IX Item "FLASH_SOCKET_POLICY" .PD \&\s-1FLASH_SOCKET_POLICY_SUPPORT\s0 defaults to disabled. .Sp When it's enabled, Feersum will detect a Flash \f(CW\*(C`\*(C'\fR packet and respond with the \s-1FLASH_SOCKET_POLICY\s0 string. .Sp The default \s-1FLASH_SOCKET_POLICY\s0 string looks like this: .Sp .Vb 6 \& \& \& \& \& \& .Ve .Sp Since that's fairly wide-open, you may not wish to enable \&\s-1FLASH_SOCKET_POLICY_SUPPORT.\s0 .Sp Note that this feature likely won't work if you use a front-end \s-1HTTP\s0 server (e.g. nginx) since the request isn't valid \s-1HTTP.\s0 .IP "\s-1FEERSUM_IOMATRIX_SIZE\s0" 4 .IX Item "FEERSUM_IOMATRIX_SIZE" Controls the size of the main write-buffer structure in Feersum. Making this value lower will use slightly less memory per connection at the cost of speed (and vice-versa for raising the value). The effect is most noticeable when you're app is making a lot of sparce writes. The default of 64 generally keeps usage under 4k per connection on full 64\-bit platforms when you take into account the other connection and request structures. .Sp \&\fB\s-1NOTE\s0\fR: \s-1FEERSUM_IOMATRIX_SIZE\s0 cannot exceed your \s-1OS\s0's defined \s-1IOV_MAX\s0 or \&\s-1UIO_MAXIOV\s0 constant. Solaris defines \s-1IOV_MAX\s0 to be 16, making it the default on that platform. Linux and \s-1OSX\s0 seem to set this at 1024. .IP "\s-1FEERSUM_STEAL\s0" 4 .IX Item "FEERSUM_STEAL" For non-threaded perls >= 5.12.0, this defaults to enabled. .Sp When enabled, Feersum will \*(L"steal\*(R" the contents of temporary lexical scalars used for response bodies. The scalars become \f(CW\*(C`undef\*(C'\fR as a result, but due to them being temps they likely aren't used again anyway. Stealing saves the time and memory needed to make a copy of that scalar, resulting in a mild to moderate performance boost. .Sp This egregious hack only extends to non-magical, string, \f(CW\*(C`PADTMP\*(C'\fR scalars. .Sp If it breaks for your new version of perl, please send stash a note (or a pull request!) on github. .Sp Worth noting is that a similar zero-copy effect can be achieved by using the \&\f(CW\*(C`psgix.body.scalar_refs\*(C'\fR feature. .SH "BUGS" .IX Header "BUGS" Please report bugs using http://github.com/stash/Feersum/issues/ .PP Keep-alive is ignored completely. .PP Currently there's no way to limit the request entity length of a \fBstreaming\fR POST/PUT/etc. This could lead to a DoS attack on a Feersum server. Suggested remedy is to only run Feersum behind some other web server and to use that to limit the entity size. .PP Although not explicitly a bug, the following may cause undesirable behavior. Feersum will have set \s-1SIGPIPE\s0 to be ignored by the time your handler gets called. If your handler needs to detect \s-1SIGPIPE,\s0 be sure to do a \&\f(CW\*(C`local $SIG{PIPE} = ...\*(C'\fR (perlipc) to make it active just during the necessary scope. .SH "SEE ALSO" .IX Header "SEE ALSO" http://en.wikipedia.org/wiki/Feersum_Endjinn .PP Feersum Git: \f(CW\*(C`http://github.com/stash/Feersum\*(C'\fR \&\f(CW\*(C`git://github.com/stash/Feersum.git\*(C'\fR .PP picohttpparser Git: \f(CW\*(C`http://github.com/kazuho/picohttpparser\*(C'\fR \&\f(CW\*(C`git://github.com/kazuho/picohttpparser.git\*(C'\fR .SH "AUTHOR" .IX Header "AUTHOR" Jeremy Stashewsky, \f(CW\*(C`stash@cpan.org\*(C'\fR .SH "THANKS" .IX Header "THANKS" Tatsuhiko Miyagawa for \s-1PSGI\s0 and Plack. .PP Marc Lehmann for \s-1EV\s0 and AnyEvent (not to mention \s-1JSON::XS\s0 and Coro). .PP Kazuho Oku for picohttpparser. .PP Luke Closs (lukec), Scott McWhirter (konobi), socialtexters and van.pm for initial feedback and ideas. Audrey Tang and Graham Termarsch for \s-1XS\s0 advice. .PP Hans Dieter Pearcey (confound) for docs and packaging guidance. .PP For bug reports: Chia-liang Kao (clkao), Lee Aylward (leedo) .PP Audrey Tang (au) for flash socket policy support. .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright (C) 2011 by Jeremy Stashewsky .PP Portions Copyright (C) 2010 Socialtext Inc. .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.7 or, at your option, any later version of Perl 5 you may have available. .PP picohttpparser is Copyright 2009 Kazuho Oku. It is released under the same terms as Perl itself.