Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial commit, still broken, not ready yet.

  • Loading branch information...
commit fa96685cc07180cb67ec1bd49cd993e83c103c4f 0 parents
Timothy Totten authored
Showing with 105 additions and 0 deletions.
  1. +2 −0  .gitignore
  2. +36 −0 README
  3. +67 −0 lib/HTTP/Easy.pm
2  .gitignore
@@ -0,0 +1,2 @@
+*.swp
+*~
36 README
@@ -0,0 +1,36 @@
+HTTP::Easy
+-----------
+
+Perl 6 libraries to make HTTP servers easily. Inspired by HTTP::Server::Simple.
+Eventually this will also include HTTP::Easy::Client but that's not high priority right now.
+
+= HTTP::Easy =
+
+A role to build custom HTTP servers. Provides the framework for parsing HTTP connections.
+The classes implementing this must provide the rest, and send the appropriate output.
+
+= HTTP::Easy::PSGI =
+
+A class implementing HTTP::Easy. This builds a PSGI environment, and passes it onto
+a handler. The handler must return a PSGI response (e.g.: [ $status, @headers, @body ] )
+This can be used as an engine in the WWW::App library.
+
+= HTTP::Easy::SCGI =
+
+A class implementing HTTP::Easy. This uses SCGI::Client to send a request to an SCGI daemon.
+It will receive the reply from the SCGI daemon, and parse it accordingly (it automatically
+detects if NPH output was returned.)
+
+= Examples =
+
+See the examples in the 'examples/' folder.
+
+= Author =
+
+Timothy Totten
+http://huri.net/
+http://github.com/supernovus/
+
+= License =
+
+Artistic License 2.0
67 lib/HTTP/Easy.pm
@@ -0,0 +1,67 @@
+## A simple HTTP Daemon role. Inspired by HTTP::Server::Simple
+## This doesn't do anything by itself, and must be extended.
+## See HTTP::Easy::PSGI and HTTP::Easy::SCGI for implementations
+## using this role.
+
+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.
+
+}
+
+## End of role.
+
Please sign in to comment.
Something went wrong with that request. Please try again.