Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Debugging made explicit. Added PSGI mode, and a test for it.

  • Loading branch information...
commit 7b86ab9a060be7e7b21c316e19fda5b879d6a681 1 parent ab50f0a
@supernovus authored
Showing with 85 additions and 25 deletions.
  1. +18 −0 PSGI-test.p6
  2. +15 −11 README
  3. +1 −1  SCGI-test.p6
  4. +51 −13 lib/SCGI.pm
View
18 PSGI-test.p6
@@ -0,0 +1,18 @@
+#!/usr/bin/env perl6
+
+BEGIN { @*INC.push: './lib'; }
+
+use SCGI;
+
+my $scgi = SCGI.new( :port(8118), :!strict, :PSGI, :debug );
+
+my $handler = sub (%env) {
+ my $name = %env<QUERY_STRING> || 'World';
+ my $status = '200';
+ my @headers = [ 'Content-Type' => 'text/plain' ];
+ my @body = [ "Hello $name\n"; ];
+ return [ $status, @headers, @body ];
+}
+
+$scgi.handle: $handler;
+
View
26 README
@@ -8,11 +8,16 @@ Perl 6 HTTP::Daemon library.
It offers a bit of candy coating compared to the Perl 5 version.
+It also offers an optional (but recommended) PSGI interface.
+
The environment contains three special keys:
- Request.Body is the request body (usually from an HTTP POST.)
- Request.Object is a reference to the individual request object.
- Request.SCGI is a reference to the SCGI object itself.
+ SCGI.Body is the request body (usually from an HTTP POST.)
+ SCGI.Object is a reference to the individual request object.
+ SCGI.SCGI is a reference to the SCGI object itself.
+
+If you use the PSGI setting, the standard PSGI variables will be added
+to the environment too.
Also, you don't need to create your own IO::Socket::INET object.
Just pass an 'addr' and 'port' attribute to the new() declaration and it'll
@@ -23,24 +28,23 @@ documentation, there is a convenience method called 'handle' that does
the heavy lifting for you:
-
use SCGI;
- my $scgi = SCGI.new( :addr<localhost>, :port(8080) );
+ my $scgi = SCGI.new( :addr<localhost>, :port(8080), :PSGI );
my $handler = sub (%env) {
my $name = %env<QUERY_STRING> // 'world';
- my $response = "Content-Type: text/plain\n\n";
- $response ~= "Hello $name\n";
- return $response;
+ my $status = '200';
+ my @headers = [ 'Content-Type' => 'text/plain' ];
+ my @body = [ "Hello $name\n" ];
+ return [ $status, @headers, @body ];
}
$scgi.handle: $handler;
-
-The output of the handler will be sent as the SCGI response,
-so make it a valid CGI response.
+If you are not using the PSGI interface, the output of the handler will be
+sent as the SCGI response, so make sure it is a valid CGI response!
** Apache configuration:
View
2  SCGI-test.p6
@@ -4,7 +4,7 @@ BEGIN { @*INC.push: './lib'; }
use SCGI;
-my $scgi = SCGI.new( :port(8118), :!strict );
+my $scgi = SCGI.new( :port(8118) );
my $handler = sub (%env) {
my $name = %env<QUERY_STRING> || 'World';
View
64 lib/SCGI.pm
@@ -7,6 +7,7 @@ class SCGI::Request {
has $.body is rw;
has $.request is rw;
has $!closed is rw = 0;
+ has $.debug = False;
method err (
$message,
@@ -26,9 +27,11 @@ class SCGI::Request {
method parse {
$.request = $.connection.get();#recv();
- $*ERR.say: "Receieved request: $.request";
+ if $.debug { $*ERR.say: "Receieved request: $.request"; }
if $.request ~~ / ^ (\d+) \: / {
- $*ERR.say: "A proper request was received, parsing into an ENV";
+ if $.debug {
+ $*ERR.say: "A proper request was received, parsing into an ENV";
+ }
my $length = +$0;
my $offset = $0.Str.chars + 1;
my $env_string = $.request.substr($offset, $length);
@@ -81,29 +84,64 @@ class SCGI {
has $.requestkey = 'SCGI.Request';
has $.scgikey = 'SCGI.Object';
+ has $.PSGI = False; ## Set to true to use PSGI mode.
+
+ has $.debug = False; ## Set to true to debug stuff.
+
has $.strict = True;
method accept () {
- $*ERR.say: "Waiting for connection.";
+ if ($.debug) {
+ $*ERR.say: "Waiting for connection.";
+ }
my $connection = self.socket.accept() or return;
- $*ERR.say: "connection family is "~$connection.family;
- $*ERR.say: "connection proto is "~$connection.proto;
- $*ERR.say: "connection type is "~$connection.type;
- SCGI::Request.new( :connection($connection), :strict($.strict) );
+ if ($.debug) {
+ $*ERR.say: "connection family is "~$connection.family;
+ $*ERR.say: "connection proto is "~$connection.proto;
+ $*ERR.say: "connection type is "~$connection.type;
+ }
+ SCGI::Request.new( :connection($connection), :$.strict, :$.debug );
}
method handle (&closure) {
- $*ERR.say: "socket family is "~$.socket.family;
- $*ERR.say: "socket proto is "~$.socket.proto;
- $*ERR.say: "socket type is "~$.socket.type;
+ if ($.debug) {
+ $*ERR.say: "socket family is "~$.socket.family;
+ $*ERR.say: "socket proto is "~$.socket.proto;
+ $*ERR.say: "socket type is "~$.socket.type;
+ }
+ $*ERR.say: "[{time}] SCGI is ready and waiting.";
while (my $request = self.accept) {
- $*ERR.say: "Doing the loop";
+ if ($.debug) { $*ERR.say: "Doing the loop"; }
if $request.parse {
my %env = $request.env;
%env{$.requestkey} = $request;
%env{$.scgikey} = self;
- %env{$.bodykey} = $request.body;
- $request.connection.send(closure(%env));
+ %env{$.bodykey} = $request.body;
+ if ($.PSGI)
+ {
+ %env<psgi.version> = [1,0];
+ %env<psgi.url_scheme> = 'http'; ## FIXME: detect this.
+ %env<psgi.multithread> = False;
+ %env<psgi.multiprocess> = False;
+ %env<psgi.input> = $request.body; ## ??
+ %env<psgi.errors> = $*ERR; ## Allow override?
+ %env<psgi.run_once> = False;
+ %env<psgi.nonblocking> = False; ## Allow when NBIO.
+ %env<psgi.streaming> = False; ## Eventually?
+ }
+ my $return = closure(%env);
+ my $output;
+ if ($.PSGI)
+ {
+ my $headers = "Status: "~$return[0]~"\n";
+ for @($return[1]) -> $header {
+ $headers ~= $header.key ~ ": " ~ $header.value ~ "\n";
+ }
+ my $body = $return[2].join("\n");
+ $output = "$headers\n$body";
+ }
+ else { $output = $return; }
+ $request.connection.send($output);
$request.close;
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.