]> Sergey Matveev's repositories - public-inbox.git/blobdiff - lib/PublicInbox/HTTP.pm
favor procedural calls for most private functions
[public-inbox.git] / lib / PublicInbox / HTTP.pm
index 4d771f2bfcdcee160c17e2743e85c58a96a04c2e..aaae7ab5c41424c10dd98a83cf7c56e68a3db2cc 100644 (file)
@@ -17,7 +17,6 @@ use HTTP::Parser::XS qw(parse_http_request); # supports pure Perl fallback
 use HTTP::Status qw(status_message);
 use HTTP::Date qw(time2str);
 use IO::File;
-my $null_io = IO::File->new('/dev/null', '<');
 use constant {
        CHUNK_START => -1,   # [a-f0-9]+\r\n
        CHUNK_END => -2,     # \r\n
@@ -25,6 +24,14 @@ use constant {
        CHUNK_MAX_HDR => 256,
 };
 
+my $null_io = IO::File->new('/dev/null', '<');
+my $http_date;
+my $prev = 0;
+sub http_date () {
+       my $now = time;
+       $now == $prev ? $http_date : ($http_date = time2str($prev = $now));
+}
+
 sub new ($$$) {
        my ($class, $sock, $addr, $httpd) = @_;
        my $self = fields::new($class);
@@ -61,7 +68,7 @@ sub rbuf_process {
 
        # We do not support Trailers in chunked requests, for now
        # (they are rarely-used and git (as of 2.7.2) does not use them)
-       return $self->quit(400) if $r == -1 || $env{HTTP_TRAILER};
+       return quit($self, 400) if $r == -1 || $env{HTTP_TRAILER};
        return $self->watch_read(1) if $r < 0; # incomplete
        $self->{rbuf} = substr($self->{rbuf}, $r);
        my $len = input_prepare($self, \%env);
@@ -83,7 +90,7 @@ sub event_read_input ($) {
        while ($len > 0) {
                if ($$rbuf ne '') {
                        my $w = write_in_full($input, $rbuf, $len);
-                       return $self->write_err unless $w;
+                       return write_err($self) unless $w;
                        $len -= $w;
                        die "BUG: $len < 0 (w=$w)" if $len < 0;
                        if ($len == 0) { # next request may be pipelined
@@ -93,7 +100,7 @@ sub event_read_input ($) {
                        $$rbuf = '';
                }
                my $r = sysread($sock, $$rbuf, 8192);
-               return $self->recv_err($r, $len) unless $r;
+               return recv_err($self, $r, $len) unless $r;
                # continue looping if $r > 0;
        }
        app_dispatch($self);
@@ -148,7 +155,7 @@ sub response_header_write {
                        ($conn =~ /\bkeep-alive\b/i);
 
        $h .= 'Connection: ' . ($alive ? 'keep-alive' : 'close');
-       $h .= "\r\nDate: " . time2str(time) . "\r\n\r\n";
+       $h .= "\r\nDate: " . http_date() . "\r\n\r\n";
 
        if (($len || $chunked) && $env->{REQUEST_METHOD} ne 'HEAD') {
                more($self, $h);
@@ -201,10 +208,9 @@ sub event_write {
        # only continue watching for readability when we are done writing:
        return if $self->write(undef) != 1;
 
-       if ($self->{rbuf} eq '') {
+       if ($self->{rbuf} eq '') { # wait for next request
                $self->watch_read(1);
-       } else {
-               # avoid recursion for pipelined requests
+       } else { # avoid recursion for pipelined requests
                Danga::Socket->AddTimer(0, sub { rbuf_process($self) });
        }
 }
@@ -232,7 +238,7 @@ sub write_err {
        my $err = $self->{env}->{'psgi.errors'};
        my $msg = $! || '(zero write)';
        $err->print("error buffering to input: $msg\n");
-       $self->quit(500);
+       quit($self, 500);
 }
 
 sub recv_err {
@@ -244,7 +250,7 @@ sub recv_err {
        }
        my $err = $self->{env}->{'psgi.errors'};
        $err->print("error reading for input: $! ($len bytes remaining)\n");
-       $self->quit(500);
+       quit($self, 500);
 }
 
 sub write_in_full {
@@ -272,20 +278,20 @@ sub event_read_input_chunked { # unlikely...
        while (1) { # chunk start
                if ($len == CHUNK_ZEND) {
                        return app_dispatch($self) if $$rbuf =~ s/\A\r\n//s;
-                       return $self->quit(400) if length($$rbuf) > 2;
+                       return quit($self, 400) if length($$rbuf) > 2;
                }
                if ($len == CHUNK_END) {
                        if ($$rbuf =~ s/\A\r\n//s) {
                                $len = CHUNK_START;
                        } elsif (length($$rbuf) > 2) {
-                               return $self->quit(400);
+                               return quit($self, 400);
                        }
                }
                if ($len == CHUNK_START) {
                        if ($$rbuf =~ s/\A([a-f0-9]+).*?\r\n//i) {
                                $len = hex $1;
                        } elsif (length($$rbuf) > CHUNK_MAX_HDR) {
-                               return $self->quit(400);
+                               return quit($self, 400);
                        }
                        # will break from loop since $len >= 0
                }
@@ -293,7 +299,7 @@ sub event_read_input_chunked { # unlikely...
                if ($len < 0) { # chunk header is trickled, read more
                        my $off = length($$rbuf);
                        my $r = sysread($sock, $$rbuf, 8192, $off);
-                       return $self->recv_err($r, $len) unless $r;
+                       return recv_err($self, $r, $len) unless $r;
                        # (implicit) goto chunk_start if $r > 0;
                }
                $len = CHUNK_ZEND if $len == 0;
@@ -302,7 +308,7 @@ sub event_read_input_chunked { # unlikely...
                until ($len <= 0) {
                        if ($$rbuf ne '') {
                                my $w = write_in_full($input, $rbuf, $len);
-                               return $self->write_err unless $w;
+                               return write_err($self) unless $w;
                                $len -= $w;
                                if ($len == 0) {
                                        # we may have leftover data to parse
@@ -318,7 +324,7 @@ sub event_read_input_chunked { # unlikely...
                        if ($$rbuf eq '') {
                                # read more of current chunk
                                my $r = sysread($sock, $$rbuf, 8192);
-                               return $self->recv_err($r, $len) unless $r;
+                               return recv_err($self, $r, $len) unless $r;
                        }
                }
        }