From: Jakub Narebski <jnareb@gmail.com>
To: git@vger.kernel.org
Subject: [RFC/PATCH 6/6] gitweb: Make possible to run under mod_perl without ParseHeaders
Date: Thu, 28 Dec 2006 01:06:24 +0100 [thread overview]
Message-ID: <200612280106.24331.jnareb@gmail.com> (raw)
In-Reply-To: <200612272355.31923.jnareb@gmail.com>
Add mod_perl version of http_header, setting headers directly (both
for mod_perl 2.0 and 1.0); bits of code taken from CGI and CGI::Util
modules. While at it add cache validation via $r->meets_conditions()
in mod_perl code.
Separate HTTP redirection into http_redirect subroutine and add
mod_perl version, setting headers directly.
All this is meant to allow gitweb to run under ModPerl::Registry (for
mod_perl 2.0) / Apache::Registry (for mod_perl 1.0) without need for
Apache to parse headers (without ParseHeaders), which should speed up
gitweb a bit.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
This patch tries to add HTTP headers directly, allowing Apache to not
need to parse headers (without ParseHeaders), which should speed
up gitweb a bit. It also makes use of mod_perl meets_expectation
method to respond to If-Modified-Since: and If-None-Match: requests
for cache validation. Current state is a bit of mess as it is now.
Comments (and patches) appreciated.
It is not benchmarked because ApacheBench went crazy, showing *negative*
waiting time. Probably I did something wrong...
Not checked for warnings, only slightly tested: definitely an RFC.
gitweb/gitweb.perl | 137 +++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 130 insertions(+), 7 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 2900ae6..12f1cb2 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -35,13 +35,17 @@ BEGIN {
require Apache2::ServerRec;
require Apache2::Response;
require Apache2::Const;
+ require APR::Date;
Apache2::RequestRec->import();
Apache2::ServerRec->import();
Apache2::Const->import(-compile => qw(:common :http));
+ APR::Date->import();
} elsif (MP_GEN == 1) {
require Apache;
require Apache::Constants;
+ require Apache::File;
import Apache;
+ import Apache::File;
Apache::Constants->import(qw(:common :http));
}
@@ -1727,11 +1731,129 @@ sub blob_mimetype {
sub http_header {
my @header = @_;
- print $cgi->header(@header);
+ if (MP_GEN) {
+ my %header = @header;
+ my $cache_validator;
+
+ ## special cases ##
+ # -status
+ $r->status_line($header{-status})
+ if $header{-status};
+ delete $header{-status} if exists $header{-status};
+ # -type and -charset
+ if ($header{-type} || $header{-charset}) {
+ my $type = $header{-type} || 'text/html';
+ $type .= "; charset=$header{-charset}"
+ if $type =~ m!^text/! and $type !~ /\bcharset\b/ and $header{-charset};
+
+ $r->content_type($type);
+ }
+ delete $header{-type} if exists $header{-type};
+ delete $header{-charset} if exists $header{-charset};
+ # -content_encoding
+ $r->content_encoding($header{-content_encoding})
+ if $header{-content_encoding};
+ delete $header{-content_encoding} if exists $header{-content_encoding};
+ # -expires
+ if ($header{-expires}) {
+ my $expires = CGI::Util::expires($header{-expires}, 'http');
+ if (MP_GEN == 1) {
+ $r->header_out('Expires', $expires);
+ } else {
+ $r->headers_out->add('Expires', $expires);
+ }
+ }
+ delete $header{-expires} if exists $header{-expires};
+ # -last_modified
+ if ($header{-last_modified}) {
+ $cache_validator ||= 1;
+ if (MP_GEN == 1) {
+ $r->header_out('Last-Modified', $header{-last_modified});
+ } else {
+ $r->set_last_modified(APR::Date::parse_http($header{-last_modified}));
+ }
+ }
+ delete $header{-last_modified} if exists $header{-last_modified};
+
+ ## other headers ##
+ while (my ($key, $value) = each %header) {
+ $key =~ s/^-//; # -content_disposition -> content_disposition
+ $key =~ s/_/-/; # content_disposition -> content-disposition
+ $key =~ s/(\w)(\w*)/\u$1$2/g;
+ # content-disposition -> Content-Disposition
+
+ if (MP_GEN == 1) {
+ $r->header_out($key, $value);
+ } else {
+ $r->headers_out->add($key, $value);
+ }
+ }
+ $cache_validator ||= (exists $header{-ETag} || exists $header{-etag});
+
+ ## send headers / flush ##
+ if (MP_GEN == 1) {
+ $r->send_http_headers();
+
+ ## validate cache ##
+ if ($cache_validator &&
+ (my $rc = $r->meets_conditions()) != Apache::Constant::OK) {
+ return $rc;
+ }
+ } else {
+ $r->rflush();
+
+ ## validate cache ##
+ if ($cache_validator &&
+ (my $rc = $r->meets_conditions()) != Apache2::Const::OK) {
+ return $rc;
+ }
+ }
+ } else {
+ print $cgi->header(@header);
+ }
# Optimization: skip generating the body if client asks only
# for HTTP header (e.g. cache validation).
- return if ($cgi->request_method() eq 'HEAD');
+ if (MP_GEN == 2) {
+ return Apache2::Const::OK if $r->header_only();
+ } elsif (MP_GEN == 1) {
+ return Apache::Constant::OK if $r->header_only();
+ } else {
+ return if ($cgi->request_method() eq 'HEAD');
+ }
+}
+
+sub http_redirect {
+ my @params = @_;
+ my %params;
+ if (@params % 2 == 0) {
+ %params = @params;
+ }
+ my $uri = $params{-uri} || $params{-url} || $params{-location}
+ || $params[0] || $cgi->self_url;
+ my $status = $params{-status};
+
+ if (MP_GEN == 1) {
+ $r->header_out('Location', $uri);
+ if (defined $status) {
+ $r->status_line($status);
+ } else {
+ $r->status(Apache::Constant::REDIRECT);
+ }
+
+ $r->send_http_headers();
+ } elsif (MP_GEN == 2) {
+ $r->headers_out->add('Location', $uri);
+ if (defined $status) {
+ $r->status_line($status);
+ } else {
+ $r->status(Apache2::Const::REDIRECT);
+ }
+
+ $r->rflush();
+ } else {
+ print $cgi->redirect(@params);
+ }
}
sub git_header_html {
@@ -1854,7 +1976,8 @@ EOF
$cgi->hidden(-name => "a") . "\n" .
$cgi->hidden(-name => "h") . "\n" .
$cgi->popup_menu(-name => 'st', -default => 'commit',
- -values => ['commit', 'author', 'committer', 'pickaxe']) .
+ -values => ['commit', 'author', 'committer',
+ gitweb_check_feature('pickaxe') ? 'pickaxe' : ()]) .
$cgi->sup($cgi->a({-href => href(action=>"search_help")}, "?")) .
" search:\n",
$cgi->textfield(-name => "s", -value => $searchtext) . "\n" .
@@ -3901,10 +4024,10 @@ sub git_object {
die_error('404 Not Found', "Not enough information to find object");
}
- print $cgi->redirect(-uri => href(action=>$type, -full=>1,
- hash=>$hash, hash_base=>$hash_base,
- file_name=>$file_name),
- -status => '302 Found');
+ http_redirect(-uri => href(action=>$type, -full=>1,
+ hash=>$hash, hash_base=>$hash_base,
+ file_name=>$file_name),
+ -status => '302 Found');
}
sub git_blobdiff {
--
1.4.4.3
next prev parent reply other threads:[~2006-12-28 0:04 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-12-27 22:55 [PATCH 0/6] gitweb: Some mod_perl specific support (but not only) Jakub Narebski
2006-12-27 22:57 ` [PATCH 1/6] gitweb: Separate HTTP header output Jakub Narebski
2006-12-28 1:23 ` Junio C Hamano
2006-12-28 1:28 ` Shawn Pearce
2006-12-27 22:59 ` [PATCH 2/6] gitweb: Add mod_perl version string to "generator" meta header Jakub Narebski
2006-12-27 23:00 ` [PATCH 3/6] gitweb: Precompile CGI routines for mod_perl Jakub Narebski
2006-12-27 23:04 ` [PATCH/RFC 4/6] gitweb: Prepare for mod_perl specific support Jakub Narebski
2006-12-27 23:49 ` [PATCH/RFC 5/6] gitweb: Make possible to run under mod_perl without SetupEnv Jakub Narebski
2006-12-28 0:06 ` Jakub Narebski [this message]
2006-12-28 1:03 ` [RFC/PATCH 6/6] gitweb: Make possible to run under mod_perl without ParseHeaders Robert Fitzsimons
2006-12-28 1:12 ` 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
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=200612280106.24331.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.
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 NNTP newsgroup(s).