| 1 | package HTTP::Engine::Interface::ModPerl; |
|---|
| 2 | use HTTP::Engine::Interface |
|---|
| 3 | builder => '+HTTP::Engine::Interface::ModPerl::RequestBuilder', |
|---|
| 4 | writer => { |
|---|
| 5 | attribute => { |
|---|
| 6 | chunk_size => { |
|---|
| 7 | is => 'ro', |
|---|
| 8 | isa => 'Int', |
|---|
| 9 | default => 4096, |
|---|
| 10 | } |
|---|
| 11 | }, |
|---|
| 12 | finalize => sub { |
|---|
| 13 | my ($self, $req, $res) = @_; |
|---|
| 14 | my $r = $req->_connection->{apache_request} or die "missing apache request"; |
|---|
| 15 | $r->status( $res->status ); |
|---|
| 16 | $req->headers->scan( |
|---|
| 17 | sub { |
|---|
| 18 | my ($key, $val) = @_; |
|---|
| 19 | $r->headers_out->add($key => $val); |
|---|
| 20 | } |
|---|
| 21 | ); |
|---|
| 22 | |
|---|
| 23 | sub { |
|---|
| 24 | my ($r, $body) = @_; |
|---|
| 25 | no warnings 'uninitialized'; |
|---|
| 26 | if ((Scalar::Util::blessed($body) && $body->can('read')) || (ref($body) eq 'GLOB')) { |
|---|
| 27 | while (!eof $body) { |
|---|
| 28 | read $body, my ($buffer), $self->chunk_size; |
|---|
| 29 | last unless $r->print($buffer); |
|---|
| 30 | } |
|---|
| 31 | close $body; |
|---|
| 32 | } else { |
|---|
| 33 | $r->print($body); |
|---|
| 34 | } |
|---|
| 35 | }->($r, $res->body); |
|---|
| 36 | }, |
|---|
| 37 | } |
|---|
| 38 | ; |
|---|
| 39 | |
|---|
| 40 | |
|---|
| 41 | BEGIN |
|---|
| 42 | { |
|---|
| 43 | if (! exists $ENV{MOD_PERL_API_VERSION} || |
|---|
| 44 | $ENV{MOD_PERL_API_VERSION} != 2) |
|---|
| 45 | { |
|---|
| 46 | die "HTTP::Engine::Interface::ModPerl only supports mod_perl2"; |
|---|
| 47 | } |
|---|
| 48 | } |
|---|
| 49 | |
|---|
| 50 | use Apache2::Const -compile => qw(OK); |
|---|
| 51 | use Apache2::Connection; |
|---|
| 52 | use Apache2::RequestRec; |
|---|
| 53 | use Apache2::RequestIO (); |
|---|
| 54 | use Apache2::RequestUtil; |
|---|
| 55 | use Apache2::ServerRec; |
|---|
| 56 | use APR::Table; |
|---|
| 57 | use HTTP::Engine; |
|---|
| 58 | |
|---|
| 59 | has 'apache' => ( |
|---|
| 60 | is => 'rw', |
|---|
| 61 | isa => 'Apache2::RequestRec', |
|---|
| 62 | is_weak => 1, |
|---|
| 63 | ); |
|---|
| 64 | |
|---|
| 65 | has context_key => ( |
|---|
| 66 | is => 'rw', |
|---|
| 67 | isa => 'Str', |
|---|
| 68 | ); |
|---|
| 69 | |
|---|
| 70 | no Moose; |
|---|
| 71 | |
|---|
| 72 | my %HE; |
|---|
| 73 | |
|---|
| 74 | sub handler : method |
|---|
| 75 | { |
|---|
| 76 | my $class = shift; |
|---|
| 77 | my $r = shift; |
|---|
| 78 | my $server = $r->server; |
|---|
| 79 | |
|---|
| 80 | # ModPerl is currently the only environment where the inteface comes |
|---|
| 81 | # before the actual invocation of HTTP::Engine |
|---|
| 82 | |
|---|
| 83 | my $context_key = join ':', $server->server_hostname, $server->port, $r->location; |
|---|
| 84 | my $engine = $HE{ $context_key }; |
|---|
| 85 | if (! $engine ) { |
|---|
| 86 | $engine = $class->create_engine($r, $context_key); |
|---|
| 87 | $HE{ $context_key } = $engine; |
|---|
| 88 | } |
|---|
| 89 | |
|---|
| 90 | $engine->interface->apache( $r ); |
|---|
| 91 | $engine->interface->context_key( $context_key ); |
|---|
| 92 | |
|---|
| 93 | my $connection = $r->connection; |
|---|
| 94 | |
|---|
| 95 | $engine->interface->handle_request( |
|---|
| 96 | headers => HTTP::Headers->new( |
|---|
| 97 | %{ $r->headers_in } |
|---|
| 98 | ), |
|---|
| 99 | _connection => { |
|---|
| 100 | input_handle => \*STDIN, |
|---|
| 101 | output_handle => \*STDOUT, |
|---|
| 102 | env => { |
|---|
| 103 | REQUEST_METHOD => $r->method(), |
|---|
| 104 | REMOTE_ADDR => $connection->remote_ip(), |
|---|
| 105 | SERVER_PORT => $server->port(), |
|---|
| 106 | QUERY_STRING => $r->args() || '', |
|---|
| 107 | HTTP_HOST => $r->hostname(), |
|---|
| 108 | SERVER_PROTOCOL => $r->protocol, |
|---|
| 109 | }, |
|---|
| 110 | apache_request => $r, |
|---|
| 111 | }, |
|---|
| 112 | connection_info => { |
|---|
| 113 | address => $connection->remote_ip(), |
|---|
| 114 | protocol => $r->protocol, |
|---|
| 115 | method => $r->method, |
|---|
| 116 | port => $server->port, |
|---|
| 117 | user => $r->user, |
|---|
| 118 | _https_info => undef, # TODO: implement |
|---|
| 119 | }, |
|---|
| 120 | hostname => $r->hostname, |
|---|
| 121 | ); |
|---|
| 122 | |
|---|
| 123 | return &Apache2::Const::OK; |
|---|
| 124 | } |
|---|
| 125 | |
|---|
| 126 | sub create_engine |
|---|
| 127 | { |
|---|
| 128 | my ($self, $r) = @_; |
|---|
| 129 | |
|---|
| 130 | HTTP::Engine->new( |
|---|
| 131 | interface => HTTP::Engine::Interface::ModPerl->new( |
|---|
| 132 | request_handler => sub { HTTP::Engine::Response->new(status => 200) }, |
|---|
| 133 | ) |
|---|
| 134 | ); |
|---|
| 135 | } |
|---|
| 136 | |
|---|
| 137 | sub run { die "THIS IS DUMMY" } |
|---|
| 138 | |
|---|
| 139 | __INTERFACE__ |
|---|
| 140 | |
|---|
| 141 | __END__ |
|---|
| 142 | |
|---|
| 143 | =head1 NAME |
|---|
| 144 | |
|---|
| 145 | HTTP::Engine::Interface::ModPerl - mod_perl Adaptor for HTTP::Engine |
|---|
| 146 | |
|---|
| 147 | =head1 AUTHORS |
|---|
| 148 | |
|---|
| 149 | Daisuke Maki |
|---|
| 150 | |
|---|
| 151 | Tokuhiro Matsuno |
|---|
| 152 | |
|---|
| 153 | =head1 KNOWN BUGS |
|---|
| 154 | |
|---|
| 155 | cannot get https_info |
|---|
| 156 | |
|---|
| 157 | =head1 SEE ALSO |
|---|
| 158 | |
|---|
| 159 | L<HTTP::Engine>, L<Apache2> |
|---|
| 160 | |
|---|
| 161 | =cut |
|---|