Created
September 16, 2011 00:00
-
-
Save diakopter/1220847 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
role HTTP::Easy { | |
has Int $.port = 8080; | |
has Str $.host = 'localhost'; | |
has $!listener = IO::Socket::INET.new(:localhost($.host), :localport($.port), :listen(1)); | |
has $!connection is rw; ## To be populated by accept(). | |
has %!env; ## The environment, generated by run(). | |
has $!body is rw; ## Any request body, populated by run(). | |
method run { | |
$*ERR.say: "{time} Started HTTP server."; | |
self.pre-connection; | |
while $!connection = $!listener.accept { | |
self.on-connection; | |
my $received = $!connection.recv(); | |
my @request = split("\x0D\x0A", $received); | |
my $request = shift @request; | |
my ($method, $uri, $protocol) = $request.split(/\s/); | |
unless $method eq any(<GET POST HEAD PUT DELETE>) { die "unknown HTTP method"; } | |
my ($path, $query) = $uri.split('?', 2); | |
$query //= ''; | |
## First, let's add our "known" headers. | |
%!env<REQUEST_METHOD> = $method; | |
%!env<PROTOCOL> = $protocol; | |
%!env<QUERY_STRING> = $query; | |
%!env<PATH_INFO> = $path; | |
%!env<REQUEST_URI> = $uri; | |
%!env<SERVER_NAME> = $.host; | |
%!env<SERVER_PORT> = $.port; | |
## Next, let's add HTTP request headers. | |
while my $header = shift @request { ## Will end at the first empty line. | |
my ($key, $value) = $header.split(': '); | |
if defined $key and defined $value { | |
$key ~~ s:g/\-/_/; | |
$key .= uc; | |
$key = 'HTTP_' ~ $key unless $key eq any(<CONTENT_LENGTH CONTENT_TYPE>); | |
if %!env.exists($key) { | |
%!env{$key} ~= ", $value"; | |
} | |
else { | |
%!env{$key} = $value; | |
} | |
} | |
} | |
## Anything left in @request is now the body. | |
$!body = @request.join("\x0D\x0A"); ## Put it back together with CRLF. | |
my $res = self.handler; ## Call our handler. It can return an HTTP response, or handle it itself. | |
if defined $res { | |
$!connection.send($res); | |
} | |
$!connection.close; | |
} | |
} | |
## Stub methods. Replace with your own. | |
method pre-connection {}; | |
method on-connection {}; | |
method handler {}; ## This MUST be implemented. | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment