From: Jakub Narebski <jnareb@gmail.com>
To: git@vger.kernel.org
Cc: Jakub Narebski <jnareb@gmail.com>
Subject: [RFC/PATCH 3/5] gitweb: Enable running gitweb as PSGI app, via CGI::Emulate::PSGI
Date: Sat, 3 Mar 2012 18:57:01 +0100 [thread overview]
Message-ID: <1330797423-22926-4-git-send-email-jnareb@gmail.com> (raw)
In-Reply-To: <1330797423-22926-1-git-send-email-jnareb@gmail.com>
This commit makes it possible to run gitweb as a PSGI application
(see http://plackperl.org), using any of PSGI web servers. This
includes ability to run gitweb from command line via Plack::Runner
module; just run "./gitweb.cgi --psgi" and point web browser
to http://0:5000
Gitweb uses CGI mode by default; to trigger PSGI mode one must either
pass `--psgi` or `--plackup` option to gitweb script, or the script
must be run with *.psgi filename (either copy/rename script, or make
symlink ending with *.psgi e.g. gitweb.psgi).
Besides running gitweb itself, converting its run_request() from CGI
to PSGI via CGI::Emulate::PSGI, gitweb as PSGI app also serves static
files: scripts, stylesheets and images via Plack::Middleware::Static.
Currently it assumes that positions and URLs of those assets are left
at their default values, namely that URLs end with "/static/<file>",
and that files can be found in "static/" directory relative to the
gitweb script itself. This assumption should be relaxed in future.
Currently "git instaweb --httpd=plackup" doesn't (yet!) use this newly
introduced feature: it is left for future commit.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
The major part of this series.
"./gitweb.cgi --psgi" runs web server on http://0:5000/
Documentation/gitweb.txt | 16 +++++++++
gitweb/INSTALL | 3 ++
gitweb/README | 13 ++++++--
gitweb/gitweb.perl | 80 ++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 107 insertions(+), 5 deletions(-)
diff --git a/Documentation/gitweb.txt b/Documentation/gitweb.txt
index 605a085..157903b 100644
--- a/Documentation/gitweb.txt
+++ b/Documentation/gitweb.txt
@@ -473,6 +473,22 @@ With that configuration the full path to browse repositories would be:
http://server/gitweb
+As PSGI using plackup
+~~~~~~~~~~~~~~~~~~~~~
+Gitweb can run as PSGI app (via emulation with *CGI::Emulate::PSGI*(3pm)).
+First you need to rename, copy or symlink gitweb.cgi to gitweb.psgi.
+You can run gitweb as a PSGI application from 'plackup' command line
+utility, using any *PSGI*(3) web server (see http://plackperl.org for
+a list), for example:
+
+ $ plackup --server HTTP::Server::Simple --port 8080 \
+ --host 127.0.0.1 gitweb.psgi
+
+With that configuration the full path to browse repositories would be:
+
+ http://127.0.0.1:8080/
+
+See *plackup*(1) manpage for more details.
ADVANCED WEB SERVER SETUP
-------------------------
diff --git a/gitweb/INSTALL b/gitweb/INSTALL
index 6d45406..9f55ab4 100644
--- a/gitweb/INSTALL
+++ b/gitweb/INSTALL
@@ -36,6 +36,9 @@ Requirements
The following optional Perl modules are required for extra features
- Digest::MD5 - for gravatar support
- CGI::Fast and FCGI - for running gitweb as FastCGI script
+ - CGI::Emulate::PSGI, Plack::Builder, Plack::Middleware::Static
+ for running gitweb as PSGI application, and Plack::Runner to
+ make it runnable as a standalone script
- HTML::TagCloud - for fancy tag cloud in project list view
- HTTP::Date or Time::ParseDate - to support If-Modified-Since for feeds
diff --git a/gitweb/README b/gitweb/README
index 6da4778..a435f9b 100644
--- a/gitweb/README
+++ b/gitweb/README
@@ -56,9 +56,16 @@ See also gitweb.conf(5) manpage.
Web server configuration
------------------------
Gitweb can be run as CGI script, as legacy mod_perl application (using
-ModPerl::Registry), and as FastCGI script. You can find some simple examples
-in "Example web server configuration" section in INSTALL file for gitweb (in
-gitweb/INSTALL).
+ModPerl::Registry), as FastCGI script, and as PSGI application. You
+can find some simple examples in "Example web server configuration"
+section in INSTALL file for gitweb (in gitweb/INSTALL).
+
+Note that to run as FastCGI script gitweb must be run with *.fcgi
+extension or with `--fastcgi` / `--fcgi` parameter on command line.
+To run as PSGI application gitweb must be run with *.psgi extension,
+or with `--psgi` / `--plackup` parameter on command line, or from
+PSGI web server which sets 'PLACK_ENV' or 'PLACK_SERVER' environment
+variable.
See "Webserver configuration" and "Advanced web server setup" sections in
gitweb(1) manpage.
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 22efec2..0dbdd15 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -1221,16 +1221,22 @@ sub configure_as_fcgi {
# let each child service 100 requests
our $is_last_request = sub { ++$request_number > 100 };
}
+sub configure_as_psgi {
+ our $CGI = 'PSGI'; # fake
+}
sub evaluate_argv {
my $script_name = $ENV{'SCRIPT_NAME'} || $ENV{'SCRIPT_FILENAME'} || __FILE__;
configure_as_fcgi()
if $script_name =~ /\.fcgi$/;
+ configure_as_psgi()
+ if $script_name =~ /\.psgi$/;
return unless (@ARGV);
require Getopt::Long;
Getopt::Long::GetOptions(
'fastcgi|fcgi|f' => \&configure_as_fcgi,
+ 'psgi|plack' => \&configure_as_psgi,
'nproc|n=i' => sub {
my ($arg, $val) = @_;
return unless eval { require FCGI::ProcManager; 1; };
@@ -1244,8 +1250,78 @@ sub evaluate_argv {
);
}
+# it is very similar to run() subroutine, but it would be hard to
+# extract common code; note that $*_hook variables can be set only
+# for FastCGI, so they are absent here
+sub to_psgi_app {
+ require CGI::Emulate::PSGI;
+
+ our $CGI = 'CGI';
+ our $first_request = 1;
+
+ my $app = CGI::Emulate::PSGI->handler(sub {
+ CGI::initialize_globals();
+ our $cgi = CGI->new();
+
+ run_request();
+
+ $first_request = 0;
+ });
+ return $app;
+}
+
+sub build_psgi_app {
+ require Plack::Builder;
+ require Plack::Middleware::Static;
+
+ my $sigchld_mw = sub {
+ my $app = shift;
+ sub {
+ my $env = shift;
+ local $SIG{'CHLD'} = 'DEFAULT';
+ local $SIG{'CLD'} = 'DEFAULT';
+ $app->($env);
+ };
+ };
+
+ # you're supposed to "add" middleware from outer to inner.
+ # note: Plack::Builder DSL (builder, enable_if, enable) won't work
+ # with "require Plack::Builder" outside BEGIN section.
+ my $app = to_psgi_app();
+ $app = Plack::Middleware::Static->wrap($app,
+ path => qr{(?:^|/)static/.*\.(?:js|css|png)$},
+ root => __DIR__,
+ encoding => 'utf-8', # encoding for 'text/plain' files
+ );
+ $app = $sigchld_mw->($app)
+ if (defined $SIG{'CHLD'} && $SIG{'CHLD'} eq 'IGNORE');
+
+ return $app;
+}
+
+sub run_psgi_app {
+ my $app = build_psgi_app();
+
+ # make it runnable as standalone app,
+ # like it would be run via 'plackup' utility.
+ # PLACK_ENV is set by plackup etc.
+ if ($ENV{'PLACK_ENV'} || $ENV{'PLACK_SERVER'}) {
+ return $app;
+ } else {
+ require Plack::Runner;
+
+ my $runner = Plack::Runner->new();
+ $runner->parse_options(qw(--env deployment),
+ qw(--host 127.0.0.1));
+ $runner->run($app);
+ }
+}
+
sub run {
evaluate_argv();
+ if ($CGI eq 'PSGI' || $ENV{'PLACK_ENV'} || $ENV{'PLACK_SERVER'}) {
+ return run_psgi_app();
+ }
$first_request = 1;
$pre_listen_hook->()
@@ -1266,12 +1342,12 @@ sub run {
}
}
-run();
+our $app = run();
if (defined caller) {
# wrapped in a subroutine processing requests,
# e.g. mod_perl with ModPerl::Registry, or PSGI with Plack::App::WrapCGI
- return;
+ return $app;
} else {
# pure CGI script, serving single request
exit;
--
1.7.9
next prev parent reply other threads:[~2012-03-03 17:57 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-03-03 17:56 [RFC/PATCH 0/5] gitweb: Proof of concept of PSGI interface Jakub Narebski
2012-03-03 17:56 ` [RFC/PATCH 1/5] gitweb: Jump do DONE_REQUEST not DONE_GITWEB on error Jakub Narebski
2012-03-03 17:57 ` [RFC/PATCH 2/5] gitweb: Prepare for splitting gitweb Jakub Narebski
2012-03-03 17:57 ` Jakub Narebski [this message]
2012-03-03 17:57 ` [RFC/PATCH 4/5] gitweb.psgi: Allow passing arguments to Plack::Runner Jakub Narebski
2012-03-03 17:57 ` [RFC/PATCH 5/5] git-instaweb: Use new PSGI interface mode of gitweb Jakub Narebski
2012-03-08 14:06 ` [RFC/PATCH 6/5] gitweb.psgi: Use installed static files, if they are available Jakub Narebski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: http://vger.kernel.org/majordomo-info.html
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1330797423-22926-4-git-send-email-jnareb@gmail.com \
--to=jnareb@gmail.com \
--cc=git@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://80x24.org/mirrors/git.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).