開発環境で静的HTMLファイルとCGIをサーブする方法
開発環境で静的HTMLファイルとCGIをサーブするために、Mojoliciousを使って簡単な実装を行いました。
本番の実行環境はApacheで、開発環境では、そうではないことは、普通にあります。
開発環境で静的なHTMLとCGIの試験が行える実装を書いてみました。
使い方
morbo serve_cgi.pl
ソースコード
# serve_cgi.pl
use Mojo::Message::Response;
use File::Temp 'tempfile';
use Mojolicious::Lite;
# render CGI
app->hook(before_dispatch => sub {
my $c = shift;
my $req = $c->req;
my $path = $req->url->path;
if ($path =~ /\.cgi$/) {
my $method = $c->req->method;
my $script_name = $c->app->home->rel_file("public/$path");
# CGI Environment variable
local $ENV{AUTH_TYPE} = '';
local $ENV{CONTENT_LENGTH} = $req->headers->content_length;
local $ENV{CONTENT_TYPE} = $req->headers->content_type;
local $ENV{GATEWAY_INTERFACE} = 'CGI/1.1';
local $ENV{PATH_INFO} = $req->url->path;
local $ENV{PATH_TRANSLATED} = $req->url->path;
local $ENV{QUERY_STRING} = $req->url->query->to_string;
local $ENV{REMOTE_ADDR} = $c->tx->remote_address;
local $ENV{REMOTE_HOST} = $c->tx->remote_address;
local $ENV{REMOTE_IDENT} = '';
local $ENV{REMOTE_USER} = '';
local $ENV{REQUEST_METHOD} = $method;
local $ENV{SCRIPT_NAME} = $script_name;
local $ENV{SERVER_NAME} = 'localhost';
local $ENV{SERVER_PORT} = $c->tx->remote_port;
local $ENV{SERVER_SOFTWARE} = "Mojolicious (Perl)";
local $ENV{SERVER_PROTOCOL} = 'HTTP/1.1';
# Check script name
unless ($script_name =~ /^[a-zA-Z_0-9\/\-\.]+$/) {
die "Invalid script name";
}
# Run CGI script
my $output;
if ($method eq 'GET') {
# GET requst
$output = `$^X $script_name`;
if ($?) {
$c->res->code('505');
$c->render(text => "Internal Server Error");
}
}
elsif ($method eq 'POST') {
# POST request
my $body = $req->body;
my ($in_fh, $in_file) = tempfile;
print $in_fh $body;
close $in_fh;
$output = `$^X -pe "" $in_file | $^X $script_name`;
if ($?) {
$c->res->code('505');
$c->render(text => "Internal Server Error");
}
unlink $in_file;
}
# Header part and body part
my ($header_part, $body_part) = split("\n\n", $output, 2);
# Response
my $res = Mojo::Message::Response->new;
while (!$res->is_finished) {
$res->parse($header_part);
}
$c->res->code($res->code);
$c->res->headers($res->headers);
$c->render(data => $body_part);
}
});
get '/' => sub {
my $c = shift;
$c->reply->static('index.html');
};
app->start;
もっといい方法あるよという方は、Twitterで、教えてください。
Perlゼミ

