]> Sergey Matveev's repositories - public-inbox.git/blob - lib/PublicInbox/HTTPD.pm
No ext_urls
[public-inbox.git] / lib / PublicInbox / HTTPD.pm
1 # Copyright (C) all contributors <meta@public-inbox.org>
2 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
3
4 # wraps a listen socket for HTTP and links it to the PSGI app in
5 # public-inbox-httpd
6 package PublicInbox::HTTPD;
7 use v5.10.1;
8 use strict;
9 use Plack::Util ();
10 use Plack::Builder;
11 use PublicInbox::HTTP;
12 use PublicInbox::HTTPD::Async;
13
14 sub pi_httpd_async { PublicInbox::HTTPD::Async->new(@_) }
15
16 # we have a different env for ever listener socket for
17 # SERVER_NAME, SERVER_PORT and psgi.url_scheme
18 # envs: listener FD => PSGI env
19 sub new { bless { envs => {}, err => \*STDERR }, __PACKAGE__ }
20
21 # this becomes {srv_env} in PublicInbox::HTTP
22 sub env_for ($$$) {
23         my ($self, $srv, $client) = @_;
24         my $n = getsockname($srv) or die "not a socket: $srv $!\n";
25         my ($host, $port) = PublicInbox::Daemon::host_with_port($n);
26         {
27                 SERVER_NAME => $host,
28                 SERVER_PORT => $port,
29                 SCRIPT_NAME => '',
30                 'psgi.version' => [ 1, 1 ],
31                 'psgi.errors' => $self->{err},
32                 'psgi.url_scheme' => $client->can('accept_SSL') ?
33                                         'https' : 'http',
34                 'psgi.nonblocking' => Plack::Util::TRUE,
35                 'psgi.streaming' => Plack::Util::TRUE,
36                 'psgi.run_once'  => Plack::Util::FALSE,
37                 'psgi.multithread' => Plack::Util::FALSE,
38                 'psgi.multiprocess' => Plack::Util::TRUE,
39
40                 # We don't use this anywhere, but we can support
41                 # other PSGI apps which might use it:
42                 'psgix.input.buffered' => Plack::Util::TRUE,
43
44                 # XXX unstable API!, only GitHTTPBackend needs
45                 # this to limit git-http-backend(1) parallelism.
46                 # We also check for the truthiness of this to
47                 # detect when to use async paths for slow blobs
48                 'pi-httpd.async' => \&pi_httpd_async,
49                 'pi-httpd.app' => $self->{app},
50                 'pi-httpd.warn_cb' => $self->{warn_cb},
51         }
52 }
53
54 sub refresh_groups {
55         my ($self) = @_;
56         my $app;
57         $self->{psgi} //= $main::ARGV[0] if @main::ARGV;
58         if ($self->{psgi}) {
59                 eval { $app = Plack::Util::load_psgi($self->{psgi}) };
60                 die $@, <<EOM if $@;
61 $0 runs in /, command-line paths must be absolute
62 EOM
63         } else {
64                 require PublicInbox::WWW;
65                 my $www = PublicInbox::WWW->new;
66                 $www->preload;
67                 $app = builder {
68                         eval { enable 'ReverseProxy' };
69                         $@ and warn <<EOM;
70 Plack::Middleware::ReverseProxy missing,
71 URL generation for redirects may be wrong if behind a reverse proxy
72 EOM
73                         enable 'Head';
74                         sub { $www->call(@_) };
75                 };
76         }
77         $_->{'pi-httpd.app'} = $app for values %{$self->{envs}};
78         $self->{app} = $app;
79 }
80
81 sub post_accept_cb { # for Listener->{post_accept}
82         my ($self) = @_;
83         sub {
84                 my ($client, $addr, $srv) = @_; # $_[4] - tls_wrap (unused)
85                 PublicInbox::HTTP->new($client, $addr,
86                                 $self->{envs}->{fileno($srv)} //=
87                                         env_for($self, $srv, $client));
88         }
89 }
90
91 1;