2 package POE::Component::IRC::Plugin::NoPaste::Httpd;
7 # with out this BEGIN block, NoPaste::Httpd::* can't import them by Exporter.
8 our @ISA = qw(Exporter);
13 internal_server_error_handler);
16 Component::Server::HTTP
17 Component::IRC::Plugin::NoPaste::Template
18 Component::IRC::Plugin::NoPaste::StaticFile
19 Component::IRC::Plugin::NoPaste::Httpd::Index
20 Component::IRC::Plugin::NoPaste::Httpd::Pasted
22 use CGI::Pretty qw(:standard);
25 use Hash::Util qw(lock_keys);
28 my ($class, $nopaste) = @_;
29 my $this = bless {} => $class;
31 $this->{nopaste} = $nopaste;
33 $this->{my_alias} = undef;
34 $this->{httpd_alias} = undef;
41 __PACKAGE__, [ qw(_start shutdown) ],
51 $this->{my_alias} = 'PCI::Plugin::NoPaste::Httpd::' . $_[SESSION]->ID;
52 $_[KERNEL]->alias_set($this->{my_alias});
57 my ($req, $resp) = @_;
59 local $ENV{OUTPUT_CHARSET} = 'UTF-8';
61 # copy the content of POST to query if needed.
62 if ($req->method eq 'POST' and
63 $req->headers->content_type eq 'application/x-www-form-urlencoded' and
64 !defined $req->uri->query) {
72 local $SIG{__DIE__} = sub {
74 $last_exception = Carp::longmess(@_);
79 $retval = $this->internal_server_error_handler(
80 $req, $resp, $last_exception);
83 # complete the response
87 $resp->message(status_message($resp->code));
89 if (!length $resp->content) {
90 if ($resp->code >= 200 && $resp->code < 300) {
91 $retval = $this->internal_server_error_handler(
92 $req, $resp, 'Content handler did not set any content.');
94 elsif ($resp->code >= 300 && $resp->code < 400) {
95 # FIXME: complete a HTML which links to the destination of redirection
99 # default value of Content-Type is text/html
100 $resp->header('Content-Type') or
101 $resp->header('Content-Type' => 'text/html; charset=UTF-8');
103 # complete Content-Length
104 $resp->header('Content-Length') or
105 $resp->header('Content-Length' => length($resp->content));
107 # remove content if the method is HEAD
108 if ($req->method eq 'HEAD') {
109 $resp->content(undef);
116 $this->{httpd_alias} = POE::Component::Server::HTTP->new(
117 Port => $this->{nopaste}{config}{httpd}{port},
120 => $barrier->(\¬found_handler),
122 => $barrier->(\&css_handler),
124 => $barrier->(\&POE::Component::IRC::Plugin::NoPaste::Httpd::Index::handler),
126 => $barrier->(\&POE::Component::IRC::Plugin::NoPaste::Httpd::Index::handler),
128 => $barrier->(\&POE::Component::IRC::Plugin::NoPaste::Httpd::Pasted::handler),
131 Server => 'PCI::Plugin::NoPaste UI (Powered by PoCo::Server::HTTP)',
132 Connection => 'close',
140 $_[KERNEL]->alias_remove($this->{my_alias});
141 $_[KERNEL]->call($this->{httpd_alias} => 'shutdown');
144 sub notfound_handler {
145 my ($this, $req, $resp) = @_;
146 my $t = POE::Component::IRC::Plugin::NoPaste::Template->new(
147 -data => static_file('tmpl/error.html'));
149 status_code => '404',
150 status_message => 'Not Found',
151 requested_url => ''.$req->uri,
153 $resp->content($t->str);
158 my ($this, $req, $resp) = @_;
159 (my $path = $req->uri->path) =~ s|^/css/||;
160 my $content = static_file('css/'.$path);
162 if (defined $content) {
163 $resp->header('Content-Type' => 'text/css; charset=UTF-8');
164 $resp->content($content);
168 return notfound_handler(@_);
172 sub internal_server_error_handler {
173 my ($this, $req, $resp, $error) = @_;
176 -style => 'white-space: pre;',
181 -title => 'Internal Server Error',
182 -encoding => 'UTF-8',
184 h1('Internal Server Error'),
186 p($style, $req->as_string),
191 $resp->code(RC_INTERNAL_SERVER_ERROR);
192 $resp->message(status_message($resp->code));
193 $resp->header('Content-Type' => 'text/html; charset=UTF-8');
194 $resp->content($html);
195 return RC_INTERNAL_SERVER_ERROR;
198 sub redirect_handler {
199 # $req : HTTP::Request
200 # $resp: HTTP::Response
201 # $path: destination of the redirection
202 # $query_hash: query (can be undef)
203 my ($this, $req, $resp, $path, $query_hash) = @_;
205 $resp->header(Location => do {
206 my $uri = $req->uri->clone;
210 $uri->query_form_hash($query_hash);
211 $uri->fragment(undef);