X-Git-Url: http://www.git.stargrave.org/?a=blobdiff_plain;f=lib%2FPublicInbox%2FHTTPD.pm;h=e531ee707e6d0a81cd85dd8eee6e31f399105c3f;hb=c38111d6f3877cf31d28b0a0339d063df0fa58f6;hp=b0bf94adf7dda314d3d4bb2d134874334d1d5b75;hpb=65323f060a3db731bb9fafa004336eeb4bbb8f00;p=public-inbox.git diff --git a/lib/PublicInbox/HTTPD.pm b/lib/PublicInbox/HTTPD.pm index b0bf94ad..e531ee70 100644 --- a/lib/PublicInbox/HTTPD.pm +++ b/lib/PublicInbox/HTTPD.pm @@ -1,29 +1,36 @@ -# Copyright (C) 2016-2018 all contributors +# Copyright (C) all contributors # License: AGPL-3.0+ # wraps a listen socket for HTTP and links it to the PSGI app in # public-inbox-httpd package PublicInbox::HTTPD; +use v5.10.1; use strict; -use warnings; -use Plack::Util; -require PublicInbox::HTTPD::Async; -require PublicInbox::Daemon; +use Plack::Util (); +use Plack::Builder; +use PublicInbox::HTTP; +use PublicInbox::HTTPD::Async; sub pi_httpd_async { PublicInbox::HTTPD::Async->new(@_) } -sub new { - my ($class, $sock, $app) = @_; - my $n = getsockname($sock) or die "not a socket: $sock $!\n"; - my ($host, $port) = PublicInbox::Daemon::host_with_port($n); +# we have a different env for ever listener socket for +# SERVER_NAME, SERVER_PORT and psgi.url_scheme +# envs: listener FD => PSGI env +sub new { bless { envs => {}, err => \*STDERR }, __PACKAGE__ } - my %env = ( +# this becomes {srv_env} in PublicInbox::HTTP +sub env_for ($$$) { + my ($self, $srv, $client) = @_; + my $n = getsockname($srv) or die "not a socket: $srv $!\n"; + my ($host, $port) = PublicInbox::Daemon::host_with_port($n); + { SERVER_NAME => $host, SERVER_PORT => $port, SCRIPT_NAME => '', 'psgi.version' => [ 1, 1 ], - 'psgi.errors' => \*STDERR, - 'psgi.url_scheme' => 'http', + 'psgi.errors' => $self->{err}, + 'psgi.url_scheme' => $client->can('accept_SSL') ? + 'https' : 'http', 'psgi.nonblocking' => Plack::Util::TRUE, 'psgi.streaming' => Plack::Util::TRUE, 'psgi.run_once' => Plack::Util::FALSE, @@ -36,18 +43,48 @@ sub new { # XXX unstable API!, only GitHTTPBackend needs # this to limit git-http-backend(1) parallelism. - # The rest of our PSGI code is generic, relying - # on "pull" model using "getline" to prevent - # over-buffering. - 'pi-httpd.async' => do { - no warnings 'once'; - *pi_httpd_async - }, - ); - bless { - app => $app, - env => \%env - }, $class; + # We also check for the truthiness of this to + # detect when to use async paths for slow blobs + 'pi-httpd.async' => \&pi_httpd_async, + 'pi-httpd.app' => $self->{app}, + } +} + +sub refresh_groups { + my ($self) = @_; + my $app; + $self->{psgi} //= $main::ARGV[0] if @main::ARGV; + if ($self->{psgi}) { + eval { $app = Plack::Util::load_psgi($self->{psgi}) }; + die $@, <new; + $www->preload; + $app = builder { + eval { enable 'ReverseProxy' }; + $@ and warn <call(@_) }; + }; + } + $_->{'pi-httpd.app'} = $app for values %{$self->{envs}}; + $self->{app} = $app; +} + +sub post_accept_cb { # for Listener->{post_accept} + my ($self) = @_; + sub { + my ($client, $addr, $srv) = @_; # $_[4] - tls_wrap (unused) + PublicInbox::HTTP->new($client, $addr, + $self->{envs}->{fileno($srv)} //= + env_for($self, $srv, $client)); + } } 1;