Rand Stats

The uploading author of cpan:HANENKAMP does not match the META author of github:zostay.

HTTP::Request::Supply

cpan:HANENKAMP

NAME

HTTP::Request::Supply - A modern HTTP/1.x request parser

SYNOPSIS

use HTTP::Request::Supply;

react {
    whenever IO::Socket::Async.listen('localhost', 8080) -> $conn {
        my $envs = HTTP::Request::Supply.parse-http($conn);
        whenever $envs -> %env {
            my $res = await app(%env);
            handle-response($conn, $res);

            QUIT {
                when X::HTTP::Request::Supply::UnsupportedProtocol {
                    $conn.print("505 HTTP Version Not Supported HTTP/1.1\r\n");
                    $conn.print("Content-Length: 26\r\n");
                    $conn.print("Content-Type: text/plain\r\n\r\n");
                    $conn.print("HTTP Version Not Supported\r\n");

                    .note;
                    $conn.close;
                }

                when X::HTTP::Request::Supply::BadRequest {
                    $conn.print("400 Bad Request HTTP/1.1\r\n");
                    $conn.print("Content-Length: " ~ .message.encode.bytes ~ \r\n");
                    $conn.print("Content-Type: text/plain\r\n\r\n");
                    $conn.print(.message);
                    $conn.print("\r\n");

                    .note;
                    $conn.close;
                }

                default {
                    $conn.print("500 Internal Server Error HTTP/1.1\r\n");
                    $conn.print("Content-Length: 22\r\n");
                    $conn.print("Content-Type: text/plain\r\n\r\n");
                    $conn.print("Internal Server Error\r\n");

                    .note;
                    $conn.close;
                }
            }
        }
    }
}

DESCRIPTION

EXPERIMENTAL: The API for this module is experimental and may change.

This class provides a Supply that is able to parse a series of request frames from an HTTP/1.x connection. Given a Supply, it consumes binary input from it. It detects the request frame or frames within the stream and passes them back to any taps on the supply asynchronously as they arrive.

This Supply emits partial P6WAPI compatible environments for use by the caller. If a problem is detected in the stream, it will quit with an exception.

METHODS

sub parse-http

sub parse-http(Supply:D() :$conn, :&promise-maker) returns Supply:D

The given Supply, $conn must emit a stream of bytes. Any other data will result in undefined behavior. The parser assumes that only binary bytes will be sent and makes no particular effort to verify that assumption.

The returned supply will react whenever data is emitted on the input supply. The incoming bytes are collated into HTTP frames, which are parsed to determine the contents of the headers. Headers are encoded into strings via ISO-8859-1 (as per RFC7230 §3.2.4).

Once the headers for a given frame have been read, a partial P6WAPI compatible environment is generated from the headers and emitted to the returned Supply. The environment will be filled as follows:

over

back

No other keys will be set. A complete P6WAPI environment must contain many other keys.

DIAGNOSTICS

The following exceptions are thrown by this class while processing input, which will trigger the quit handlers on the Supply.

X::HTTP::Request::Supply::UnsupportedProtocol

This exception will be thrown if the stream does not seem to be HTTP or if the requested HTTP version is not 1.0 or 1.1.

X::HTTP::Request::Supply::BadRequest

This exception will be thrown if the HTTP request is incorrectly framed. This may happen when the request does not specify its content length using a Content-Length header or chunked Transfer-Encoding.

CAVEATS

This code aims at providing a minimal implementation that is just enough to decode the HTTP frames and provide the information about the raw requests to the tapping code. It is not safe to assume that anything provided has been validated or processed.

HTTP is complicated and hard. This implementation is not yet complete and not battle tested yet. Please report bugs to github and patches are welcome. Even once this code matures, it will never receive the TLC that a full-blown general web server is going to get as regards hardening and maturity on the Internet. As such, the author always recommends using this code behind an existing, well-known, and well-maintained web server in production. This is only ever intended as a "bare metal" application server interface.

This interface is built with the intention of making it easier to build HTTP/1.0 and HTTP/1.1 parsers for use with P6WAPI. As of this writing, that specification is only a proposed draft, so the output of this module is experimental and will change as that specification changes.

Finally, this module only takes responsibility for parsing the incoming HTTP frames. It does not manage the connection and it provides no tools for sending responses back to the user agent.

AUTHOR

Sterling Hanenkamp <hanenkamp@cpan.org>

COPYRIGHT & LICENSE

Copyright 2016 Sterling Hanenkamp.

This software is licensed under the same terms as Perl 6.