Skip to content

Instantly share code, notes, and snippets.

@VienosNotes
Last active December 31, 2015 07:49
Show Gist options
  • Select an option

  • Save VienosNotes/7956646 to your computer and use it in GitHub Desktop.

Select an option

Save VienosNotes/7956646 to your computer and use it in GitHub Desktop.
HTTP Server on Perl6(JVM/Rakudo) with Threads
use v6;
class Settings {
has Int $.port;
has Str $.document_root;
method new(Str $path) {
my @settings = $path.IO.lines;
my $portline = @settings.grep(/port\=<.digit>*$$/)[0];
my $port = $portline.substr(5).Int;
my $docline = @settings.grep(/documentRoot\=[.*]$$/)[0];
my $doc = $docline.substr(13);
return self.bless(port => $port, document_root => $doc);
}
}
class ConnectionThread {
has $.connection;
has $.settings;
has $.id;
method new(IO::Socket $soc, Settings $settings) {
return self.bless(connection => $soc, settings => $settings);
}
method start() {
$!id = self.WHICH.gist;
my Str @req = $!connection.recv().split("\r\n");
say "[Request:" ~ $!id ~ "] " ~ @req[0].gist;
my $location = @req[0].split(" ")[1];
my $doc = $!settings.document_root ~ $location;
my $response = self.load_document($doc);
$!connection.send($response // "");
$!connection.close;
}
multi method make_response(200, Str $req) {
my $content_file = ($req).IO.slurp;
say "[Response:" ~ $!id ~ "] 200 OK" ;
my $res = "HTTP/1.1 200 OK\nCache-Control: private\nContent-Type: text/html\n\n";
return $res ~ $content_file;
}
multi method make_response(403, Str $req) {
say "[Response:" ~ $!id ~ "] 403 Forbbiden" ;
my $res = "HTTP/1.1 403 Forbbiden\nCache-Control: private\nContent-Type: text/html\n\n";
$res ~= "<html><body><h1>403 Forbbiden</h1></body></html>\n";
return $res;
}
multi method make_response(404, Str $req) {
say "[Response:" ~ $!id ~ "] 404 Not Found" ;
my $res = "HTTP/1.1 404 Not Found\nCache-Control: private\nContent-Type: text/html\n\n";
$res ~= "<html><body><h1>404 Not Found</h1></body></html>\n";
return $res;
}
method load_document(Str $doc) {
given $doc {
when $doc ~~ /\.\./ {
return self.make_response(403, $doc);
}
when !$doc.IO.e {
return self.make_response(404, $doc);
}
when !$doc.IO.r {
return self.make_response(403, $doc);
}
when $doc.IO.d {
return self.make_response(403, $doc);
}
}
return self.make_response(200, $doc);
}
}
class Server {
has Settings $.settings;
method new(Str $path) {
my $s = Settings.new($path);
return self.bless(settings => $s);
}
method start() {
say "Starting Server...";
say "port: " ~ $!settings.port ~ ", documentRoot: " ~ $!settings.document_root;
my $server = IO::Socket::INET.new(:listen, localport => $!settings.port);
say $server.gist;
$server.listen;
while $server.accept -> $connection {
Thread.start({
my $ct = ConnectionThread.new($connection, $!settings);
$ct.start;
});
}
}
}
my $server = Server.new("/path/to/settings");
$server.start();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment