1POE::Filter::HTTPD(3) User Contributed Perl DocumentationPOE::Filter::HTTPD(3)
2
3
4
6 POE::Filter::HTTPD - parse simple HTTP requests, and serialize
7 HTTP::Response
8
10 #!perl
11
12 use warnings;
13 use strict;
14
15 use POE qw(Component::Server::TCP Filter::HTTPD);
16 use HTTP::Response;
17
18 POE::Component::Server::TCP->new(
19 Port => 8088,
20 ClientFilter => 'POE::Filter::HTTPD', ### <-- HERE WE ARE!
21
22 ClientInput => sub {
23 my $request = $_[ARG0];
24
25 # It's a response for the client if there was a problem.
26 if ($request->isa("HTTP::Response")) {
27 my $response = $request;
28
29 $request = $response->request;
30 warn "ERROR: ", $request->message if $request;
31
32 $_[HEAP]{client}->put($response);
33 $_[KERNEL]->yield("shutdown");
34 return;
35 }
36
37 my $request_fields = '';
38 $request->headers()->scan(
39 sub {
40 my ($header, $value) = @_;
41 $request_fields .= (
42 "<tr><td>$header</td><td>$value</td></tr>"
43 );
44 }
45 );
46
47 my $response = HTTP::Response->new(200);
48 $response->push_header( 'Content-type', 'text/html' );
49 $response->content(
50 "<html><head><title>Your Request</title></head>" .
51 "<body>Details about your request:" .
52 "<table border='1'>$request_fields</table>" .
53 "</body></html>"
54 );
55
56 $_[HEAP]{client}->put($response);
57 $_[KERNEL]->yield("shutdown");
58 }
59 );
60
61 print "Aim your browser at port 8088 of this host.\n";
62 POE::Kernel->run();
63 exit;
64
66 POE::Filter::HTTPD interprets input streams as HTTP 0.9, 1.0 or 1.1
67 requests. It returns a HTTP::Request objects upon successfully parsing
68 a request.
69
70 On failure, it returns an HTTP::Response object describing the failure.
71 The intention is that application code will notice the HTTP::Response
72 and send it back without further processing. The erroneous request
73 object is sometimes available via the "request" in HTTP::Response
74 method. This is illustrated in the "SYNOPSIS".
75
76 For output, POE::Filter::HTTPD accepts HTTP::Response objects and
77 returns their corresponding streams.
78
79 Please see HTTP::Request and HTTP::Response for details about how to
80 use these objects.
81
83 POE::Filter::HTTPD implements the basic POE::Filter interface.
84
86 Some versions of libwww are known to generate invalid HTTP. For
87 example, this code (adapted from the HTTP::Request::Common
88 documentation) will cause an error in a POE::Filter::HTTPD daemon:
89
90 NOTE: Using this test with libwww-perl/5.834 showed that it added the
91 proper HTTP/1.1 data! We're not sure which version of LWP fixed this.
92 This example is valid for older LWP installations, beware!
93
94 use HTTP::Request::Common;
95 use LWP::UserAgent;
96
97 my $ua = LWP::UserAgent->new();
98 $ua->request(POST 'http://example.com', [ foo => 'bar' ]);
99
100 By default, HTTP::Request is HTTP version agnostic. It makes no attempt
101 to add an HTTP version header unless you specifically declare a
102 protocol using "$request->protocol('HTTP/1.0')".
103
104 According to the HTTP 1.0 RFC (1945), when faced with no HTTP version
105 header, the parser is to default to HTTP/0.9. POE::Filter::HTTPD
106 follows this convention. In the transaction detailed above, the
107 Filter::HTTPD based daemon will return a 400 error since POST is not a
108 valid HTTP/0.9 request type.
109
110 Upon handling a request error, it is most expedient and reliable to
111 respond with the error and shut down the connection. Invalid HTTP
112 requests may corrupt the request stream. For example, the absence of a
113 Content-Length header signals that a request has no content. Requests
114 with content but not that header will be broken into a content-less
115 request and invalid data. The invalid data may also appear to be a
116 request! Hilarity will ensue, possibly repeatedly, until the filter
117 can find the next valid request. By shutting down the connection on
118 the first sign of error, the client can retry its request with a clean
119 connection and filter.
120
122 It is possible to use POE::Filter::HTTPD for streaming content, but an
123 application can use it to send headers and then switch to
124 POE::Filter::Stream.
125
126 From the input handler (the InputEvent handler if you're using wheels,
127 or the ClientInput handler for POE::Component::Server::TCP):
128
129 my $response = HTTP::Response->new(200);
130 $response->push_header('Content-type', 'audio/x-mpeg');
131 $_[HEAP]{client}->put($response);
132 $_[HEAP]{client}->set_output_filter(POE::Filter::Stream->new());
133
134 Then the output-flushed handler (FlushEvent for POE::Wheel::ReadWrite,
135 or ClientFlushed for POE::Component::Server::TCP) can put() chunks of
136 the stream as needed.
137
138 my $bytes_read = sysread(
139 $_[HEAP]{file_to_stream}, my $buffer = '', 4096
140 );
141
142 if ($bytes_read) {
143 $_[HEAP]{client}->put($buffer);
144 }
145 else {
146 delete $_[HEAP]{file_to_stream};
147 $_[KERNEL]->yield("shutdown");
148 }
149
151 Please see POE::Filter for documentation regarding the base interface.
152
153 The SEE ALSO section in POE contains a table of contents covering the
154 entire POE distribution.
155
156 HTTP::Request and HTTP::Response explain all the wonderful things you
157 can do with these classes.
158
160 Many aspects of HTTP 1.0 and higher are not supported, such as keep-
161 alive. A simple I/O filter can't support keep-alive, for example. A
162 number of more feature-rich POE HTTP servers are on the CPAN. See
163 <http://search.cpan.org/search?query=POE+http+server&mode=dist>
164
166 POE::Filter::HTTPD was contributed by Artur Bergman. Documentation is
167 provided by Rocco Caputo.
168
169 Please see POE for more information about authors and contributors.
170
171
172
173perl v5.12.1 2010-04-03 POE::Filter::HTTPD(3)