]> Sergey Matveev's repositories - public-inbox.git/blob - public-inbox-httpd
6436bd7df1011cbfbff3e26bb6197d59d54852d7
[public-inbox.git] / public-inbox-httpd
1 #!/usr/bin/perl -w
2 # Copyright (C) 2016 all contributors <meta@public-inbox.org>
3 # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
4 #
5 # Standalone HTTP server for public-inbox.
6 use strict;
7 use warnings;
8 use Plack::Util;
9 use PublicInbox::Daemon;
10 use PublicInbox::HTTP;
11 use PublicInbox::WWW;
12 use Plack::Request;
13 use Plack::Builder;
14 PublicInbox::WWW->preload;
15 my $have_deflater = eval { require Plack::Middleware::Deflater; 1 };
16 my %httpds;
17 my $config;
18 my $app;
19 my $refresh = sub {
20         if (@ARGV) {
21                 eval { $app = Plack::Util::load_psgi(@ARGV) };
22                 if ($@) {
23                         die $@,
24 "$0 runs in /, command-line paths must be absolute\n";
25                 }
26         } else {
27                 $app = eval {
28                         my $deflate_types = eval {
29                                 require Plack::Middleware::Deflater;
30                                 [ 'text/html', 'text/plain',
31                                         'application/atom+xml' ]
32                         };
33                         builder {
34                                 enable 'Chunked';
35                                 if ($deflate_types) {
36                                         enable 'Deflater',
37                                                 content_type => $deflate_types
38                                 }
39                                 enable 'Head';
40                                 sub {
41                                         my $req = Plack::Request->new(@_);
42                                         PublicInbox::WWW::run($req,
43                                                         $req->method);
44                                 };
45                         };
46                 };
47         }
48 };
49
50 daemon_run('0.0.0.0:8080', $refresh,
51         sub ($$$) { # post_accept
52                 my ($client, $addr, $srv) = @_;
53                 my $fd = fileno($srv);
54                 my $h = $httpds{$fd} ||= PublicInbox::HTTPD->new($srv, $app);
55                 PublicInbox::HTTP->new($client, $addr, $h),
56         });
57
58 1;
59 package PublicInbox::HTTPD;
60 use strict;
61 use warnings;
62 use Plack::Util;
63
64 sub new {
65         my ($class, $sock, $app) = @_;
66         my $n = getsockname($sock) or die "not a socket: $sock $!\n";
67         my ($port, $addr);
68         if (length($n) >= 28) {
69                 require Socket6;
70                 ($port, $addr) = Socket6::unpack_sockaddr_in6($n);
71         } else {
72                 ($port, $addr) = Socket::unpack_sockaddr_in($n);
73         }
74
75         my %env = (
76                 REMOTE_HOST => '',
77                 REMOTE_PORT => 0,
78                 SERVER_NAME => $addr,
79                 SERVER_PORT => $port,
80                 SCRIPT_NAME => '',
81                 'psgi.version' => [ 1, 1 ],
82                 'psgi.errors' => \*STDERR,
83                 'psgi.url_scheme' => 'http',
84                 'psgi.nonblocking' => Plack::Util::TRUE,
85                 'psgi.streaming' => Plack::Util::TRUE,
86                 'psgi.run_once'  => Plack::Util::FALSE,
87                 'psgi.multithread' => Plack::Util::FALSE,
88                 'psgi.multiprocess' => Plack::Util::TRUE,
89                 'psgix.harakiri'=> Plack::Util::FALSE,
90                 'psgix.input.buffered' => Plack::Util::TRUE,
91         );
92         bless {
93                 err => \*STDERR,
94                 out => \*STDOUT,
95                 app => $app,
96                 env => \%env,
97         }, $class;
98 }
99
100 1;