File Coverage

blib/lib/Net/HTTPServer/Response.pm
Criterion Covered Total %
statement 88 113 77.8
branch 25 42 59.5
condition 2 9 22.2
subroutine 15 18 83.3
pod 11 11 100.0
total 141 193 73.0


line stmt bran cond sub pod time code
1             ##############################################################################
2             #
3             # This library is free software; you can redistribute it and/or
4             # modify it under the terms of the GNU Library General Public
5             # License as published by the Free Software Foundation; either
6             # version 2 of the License, or (at your option) any later version.
7             #
8             # This library is distributed in the hope that it will be useful,
9             # but WITHOUT ANY WARRANTY; without even the implied warranty of
10             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11             # Library General Public License for more details.
12             #
13             # You should have received a copy of the GNU Library General Public
14             # License along with this library; if not, write to the
15             # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16             # Boston, MA 02111-1307, USA.
17             #
18             # Copyright (C) 2003-2005 Ryan Eatmon
19             #
20             ##############################################################################
21             package Net::HTTPServer::Response;
22              
23             =head1 NAME
24              
25             Net::HTTPServer::Response
26              
27             =head1 SYNOPSIS
28              
29             Net::HTTPServer::Response handles formatting the response to the client.
30            
31             =head1 DESCRIPTION
32              
33             Net::HTTPServer::Response provides a nice OOP interface for easy control
34             of headers, cookies, sessions, and/or the content that will be sent to
35             the requesting client.
36              
37             =head1 EXAMPLES
38              
39             my $response = new Net::HTTPServer::Response();
40              
41              
42              
43             my $response = new Net::HTTPServer::Response(code=>200,
44             headers=>{
45             );
46              
47             my $response = $request->Response();
48              
49             =head1 METHODS
50              
51             =head2 new(%cfg)
52              
53             Given a config hash, return a server object that you can start, process,
54             and stop. The config hash takes the options:
55              
56             body => string - The contents of the response.
57             ( Default: "" )
58              
59             code => int - The return code of this reponse.
60             ( Default: 200 )
61            
62             cookies => hashref - Hash reference to a set of cookies to send.
63             Most people should just use the Cookie method
64             to set these.
65             ( Default: {} )
66              
67             headers => hashref - Hash reference to the headers to send. Most
68             people should just use the Header method.
69             ( Default: {} )
70              
71             =head2 Body([string])
72              
73             Returns the current value of the response body. Sets the content of
74             the response if a value is specified.
75              
76             =head2 Clear()
77              
78             Reset the body to "".
79              
80             =head2 Code(int)
81              
82             Returns the current value of the response code. Set the status code
83             of the response if a value is specified.
84              
85             =head2 Cookie(name[,value[,%options]])
86              
87             Returns the cookie value for the specified name, or undef if it is
88             not set. If the value is also specified, then the cookie is set
89             to the value. The optional hash options that you can provide to
90             the cookie are:
91              
92             domain => string - If specified, the client will return the
93             cookie for any hostname that is part of
94             the domain.
95              
96             expires => string - When should the cookie expire. Must be
97             formatted according to the rules:
98             Wednesday, 30-June-2004 18:14:24 GMT
99             Optionally you can specify "now" which
100             will resolve to the current time.
101            
102             path => string - The path on the server that the client should
103             return the cookie for.
104              
105             secure => 0|1 - The client will only return the cookie over
106             an HTTPS connection.
107              
108             =head2 Header(name[,value])
109              
110             Returns the header value for the specified name, or undef if it is not
111             set. If the value is specified, then the header is set to the value.
112              
113             =head2 Print(arg1[,arg2,...,argN])
114              
115             Appends the arguments to the end of the body.
116              
117             =head2 Redirect(url)
118              
119             Redirect the client to the specified URL.
120              
121             =head2 Session(object)
122              
123             Register the Net::HTTPServer::Session object with the response. When
124             the server builds the actual reponse to the client it will set the
125             appropriate cookie and save the session. If the response is
126             created from the request object, and there was a session created
127             from the request object then this, will be prepopulated with that
128             session.
129              
130             =head2 CaptureSTDOUT()
131              
132             If you use the CGI perl module then it wants to print everything to
133             STDOUT. CaptureSTDOUT() will put the Reponse object into a mode
134             where it will capture all the output from the module. See
135             ProcessSTDOUT() for more information.
136              
137             =head2 ProcessSTDOUT([%args])
138              
139             This will harvest all of the data printed to STDOUT and put it into
140             the Response object via a Print() call. This will also stop
141             monitoring STDOUT and release it. You can specify some options:
142              
143             strip_header => 0|1 - If you use the CGI module and you
144             print the headers then ProcessSTDOUT()
145             can try to strip those out. The best
146             plan is not to print them.
147            
148             See CaptureSTDOUT() for more information.
149              
150             =head1 AUTHOR
151              
152             Ryan Eatmon
153              
154             =head1 COPYRIGHT
155              
156             Copyright (c) 2003-2005 Ryan Eatmon . All rights
157             reserved. This program is free software; you can redistribute it
158             and/or modify it under the same terms as Perl itself.
159              
160             =cut
161            
162 5     5   14429 use strict;
  5         14  
  5         233  
163 5     5   27 use Carp;
  5         8  
  5         356  
164 5     5   4273 use URI::Escape;
  5         7980  
  5         335  
165 5     5   3704 use Net::HTTPServer::CaptureSTDOUT;
  5         92  
  5         243  
166              
167 5     5   31 use vars qw ( $VERSION );
  5         9  
  5         12444  
168              
169             $VERSION = "1.0.3";
170              
171             sub new
172             {
173 2     2 1 286 my $proto = shift;
174 2   33     18 my $class = ref($proto) || $proto;
175 2         4 my $self = { };
176            
177 2         8 bless($self, $proto);
178              
179 2         6 my (%args) = @_;
180              
181 2         12 $self->{ARGS} = \%args;
182              
183 2         10 $self->{CODE} = $self->_arg("code","200");
184 2         7 $self->{HEADERS} = $self->_arg("headers",{});
185 2         7 $self->{COOKIES} = $self->_arg("cookies",{});
186 2         7 $self->{BODY} = $self->_arg("body","");
187              
188 2         8 return $self;
189             }
190              
191              
192             sub Body
193             {
194 8     8 1 806 my $self = shift;
195 8         15 my $body = shift;
196              
197 8 100       62 return $self->{BODY} unless defined($body);
198 1         9 $self->{BODY} = $body;
199             }
200              
201              
202             sub Clear
203             {
204 2     2 1 6 my $self = shift;
205            
206 2         10 $self->{BODY} = "";
207             }
208              
209              
210             sub Code
211             {
212 5     5 1 271 my $self = shift;
213 5         8 my $code = shift;
214              
215 5 100       25 return $self->{CODE} unless defined($code);
216 2         7 $self->{CODE} = $code;
217             }
218              
219              
220             sub Cookie
221             {
222 2     2 1 544 my $self = shift;
223 2         3 my $cookie = shift;
224 2         2 my $value = shift;
225 2         9 my (%args) = @_;
226              
227 2 50 33     14 return unless (defined($cookie) && defined($value));
228            
229 2         7 $self->{COOKIES}->{$cookie}->{value} = $value;
230 2 100       24 if (exists($args{expires}))
231             {
232 1         4 $self->{COOKIES}->{$cookie}->{expires} = $args{expires};
233 1 50       4 $self->{COOKIES}->{$cookie}->{expires} = &Net::HTTPServer::_date()
234             if ($args{expires} eq "now");
235             }
236 2 100       9 $self->{COOKIES}->{$cookie}->{domain} = $args{domain}
237             if exists($args{domain});
238 2 100       7 $self->{COOKIES}->{$cookie}->{path} = $args{path}
239             if exists($args{path});
240 2 100       9 $self->{COOKIES}->{$cookie}->{secure} = $args{secure}
241             if exists($args{secure});
242             }
243              
244              
245             sub Header
246             {
247 4     4 1 327 my $self = shift;
248 4         7 my $header = shift;
249 4         5 my $value = shift;
250              
251 4 50       15 return unless defined($header);
252 4 100       15 $self->{HEADERS}->{$header} = $value if defined($value);
253 4 50       15 return unless exists($self->{HEADERS}->{$header});
254 4         18 return $self->{HEADERS}->{$header};
255             }
256              
257              
258             sub Print
259             {
260 2     2 1 7 my $self = shift;
261            
262 2         10 $self->{BODY} .= join("",@_);
263             }
264              
265              
266             sub Redirect
267             {
268 1     1 1 277 my $self = shift;
269 1         3 my $url = shift;
270              
271 1         5 $self->Code(307);
272 1         4 $self->Clear();
273 1         5 $self->Header("Location",$url);
274             }
275              
276              
277             sub Session
278             {
279 0     0 1 0 my $self = shift;
280 0         0 my $session = shift;
281              
282 0 0       0 $self->{SESSION} = $session if defined($session);
283 0 0       0 return unless exists($self->{SESSION});
284 0         0 return $self->{SESSION};
285             }
286              
287              
288             sub CaptureSTDOUT
289             {
290 0     0 1 0 my $self = shift;
291              
292 0 0       0 if (tied *STDOUT)
293             {
294 0         0 croak("You cannot call CaptureSTDOUT more than once without calling ProcessSTDOUT");
295             }
296              
297 0         0 tie(*STDOUT, "Net::HTTPServer::CaptureSTDOUT");
298             }
299              
300              
301             sub ProcessSTDOUT
302             {
303 0     0 1 0 my $self = shift;
304 0         0 my (%args) = @_;
305              
306 0         0 my $output = join("",);
307              
308             #--------------------------------------------------------------------------
309             # Try and strip out the headers if the user printed any...
310             #--------------------------------------------------------------------------
311 0 0 0     0 if (exists($args{strip_header}) && ($args{strip_header} == 1))
312             {
313 0         0 $output =~ s/^.+\015?\012\015?\012//;
314             }
315              
316 0         0 $self->Print($output);
317              
318 0         0 untie(*STDOUT);
319             }
320              
321             ###############################################################################
322             #
323             # _arg - if the arg exists then use it, else use the default.
324             #
325             ###############################################################################
326             sub _arg
327             {
328 8     8   14 my $self = shift;
329 8         11 my $arg = shift;
330 8         10 my $default = shift;
331              
332 8 50       39 return (exists($self->{ARGS}->{$arg}) ? $self->{ARGS}->{$arg} : $default);
333             }
334              
335              
336             sub _build
337             {
338 9     9   846 my $self = shift;
339              
340             #-------------------------------------------------------------------------
341             # Format the return headers
342             #-------------------------------------------------------------------------
343 9         30 my $header = "HTTP/1.1 ".$self->{CODE}."\n";
344 9         15 foreach my $key (sort {$a cmp $b} keys(%{$self->{HEADERS}}))
  0         0  
  9         41  
345             {
346 8         38 $header .= "$key: ".$self->{HEADERS}->{$key}."\n";
347             }
348              
349             #-------------------------------------------------------------------------
350             # Session in, cookie out
351             #-------------------------------------------------------------------------
352 9 50       33 if (exists($self->{SESSION}))
353             {
354 0         0 my $value = $self->{SESSION}->_key();
355 0         0 my $delta = 4*60*60; # 4 hours from now
356              
357 0 0       0 if ($self->{SESSION}->_valid())
358             {
359 0         0 $self->{SESSION}->_save();
360             }
361             else
362             {
363 0         0 $value = "";
364 0         0 $delta = -(100*24*60*60); # 100 days ago
365             }
366              
367 0         0 $self->Cookie("NETHTTPSERVERSESSION",
368             $value,
369             expires=>&Net::HTTPServer::_date(time,$delta),
370             );
371             }
372              
373             #-------------------------------------------------------------------------
374             # Mmmm.... Cookies....
375             #-------------------------------------------------------------------------
376 9         12 foreach my $cookie (sort {$a cmp $b} keys(%{$self->{COOKIES}}))
  0         0  
  9         32  
377             {
378 6         32 my $value = uri_escape($self->{COOKIES}->{$cookie}->{value});
379            
380 6         129 $header .= "Set-Cookie: $cookie=$value";
381            
382 6         12 foreach my $key (sort {$a cmp $b} keys(%{$self->{COOKIES}->{$cookie}}))
  35         55  
  6         36  
383             {
384 26 100       68 next if ($key eq "value");
385 20 100       37 if ($key eq "secure")
386             {
387 5 50       23 if ($self->{COOKIES}->{$cookie}->{$key} == 1)
388             {
389 5         14 $header .= ";$key";
390             }
391             }
392             else
393             {
394 15         53 $header .= ";$key=".$self->{COOKIES}->{$cookie}->{$key};
395             }
396             }
397              
398 6         19 $header .= "\n";
399             }
400              
401 9         19 chomp($header);
402 9         17 $header .= "\r\n\r\n";
403              
404 9         44 return ($header,$self->{BODY});
405             }
406              
407              
408              
409              
410             1;
411