File Coverage

blib/lib/HTTP/Request/Params.pm
Criterion Covered Total %
statement 29 66 43.9
branch 1 14 7.1
condition 0 3 0.0
subroutine 9 11 81.8
pod 1 1 100.0
total 40 95 42.1


line stmt bran cond sub pod time code
1             package HTTP::Request::Params;
2             # $Id: Params.pm,v 1.1 2005/01/12 16:42:32 cwest Exp $
3 1     1   52459 use strict;
  1         2  
  1         49  
4              
5             =head1 NAME
6              
7             HTTP::Request::Params - Retrieve GET/POST Parameters from HTTP Requests
8              
9             =head1 SYNOPSIS
10              
11             use HTTP::Request::Params;
12            
13             my $http_request = read_request();
14             my $parse_params = HTTP::Request::Params->new({
15             req => $http_request,
16             });
17             my $params = $parse_params->params;
18              
19             =cut
20              
21 1     1   4 use vars qw[$VERSION];
  1         3  
  1         111  
22             $VERSION = sprintf "%d.%02d", split m/\./, (qw$Revision: 1.1 $)[1];
23              
24 1     1   16415 use CGI;
  1         70332  
  1         8  
25 1     1   6320 use Email::MIME::Modifier;
  1         339  
  1         40  
26 1     1   2753 use Email::MIME::ContentType qw[parse_content_type];
  1         1893  
  1         82  
27 1     1   1357 use HTTP::Request;
  1         66177  
  1         46  
28 1     1   12 use HTTP::Message;
  1         3  
  1         25  
29 1     1   5 use base qw[Class::Accessor::Fast];
  1         2  
  1         46399  
30              
31             =head1 DESCRIPTION
32              
33             This software does all the dirty work of parsing HTTP Requests to find
34             incoming query parameters.
35              
36             =head2 new
37              
38             my $parser = HTTP::Request::Params->new({
39             req => $http_request,
40             });
41              
42             C<req> - This required argument is either an C<HTTP::Request> object or a
43             string containing an entier HTTP Request.
44              
45             Incoming query parameters come from two places. The first place is the
46             C<query> portion of the URL. Second is the content portion of an HTTP
47             request as is the case when parsing a POST request, for example.
48              
49             =head2 params
50              
51             my $params = $parser->params;
52              
53             Returns a hash reference containing all the parameters. The keys in this hash
54             are the names of the parameters. Values are the values associated with those
55             parameters in the incoming query. For parameters with multiple values, the value
56             in this hash will be a list reference. This is the same behaviour as the C<CGI>
57             module's C<Vars()> function.
58              
59             =head2 req
60              
61             my $req_object = $parser->req;
62              
63             Returns the C<HTTP::Request> object.
64              
65             =head2 mime
66              
67             my $mime_object = $parser->mime;
68              
69             Returns the C<Email::MIME> object.
70              
71             Now, you may be wondering why we're dealing with an C<Email::MIME> object.
72             The answer is simple. It's an amazing parser for MIME compliant messages,
73             and RFC 822 compliant messages. When parsing incoming POST data, especially
74             file uploads, C<Email::MIME> is the perfect fit. It's fast and light.
75              
76             =cut
77              
78             sub new {
79 1     1 1 11301 my ($class) = shift;
80 1         15 my $self = $class->SUPER::new(@_);
81              
82 1 50       18 $self->req(HTTP::Request->parse($self->req))
83             unless ref($self->req);
84              
85 1         24 my $message = (split /\n/, $self->req->as_string, 2)[1];
86 1         358 $self->mime(Email::MIME->new($self->req->as_string));
87              
88 0           $self->_find_params;
89              
90 0           return $self;
91             }
92             __PACKAGE__->mk_accessors(qw[req mime params]);
93              
94             sub _find_params {
95 0     0     my $self = shift;
96 0           my $query_params = CGI->new($self->req->url->query)->Vars;
97 0           my $post_params = {};
98              
99 0 0         if ( $self->mime->parts > 1 ) {
100 0           foreach my $part ( $self->mime->parts ) {
101 0 0         next if $part == $self->mime;
102 0           $part->disposition_set('text/plain'); # for easy parsing
103              
104 0           my $disp = $part->header('Content-Disposition');
105 0           my $ct = parse_content_type($disp);
106 0           my $name = $ct->{attributes}->{name};
107 0           my $content = $part->body;
108              
109 0           $content =~ s/\r\n$//;
110 0           $self->_add_to_field($post_params, $name, $content);
111             }
112             } else {
113 0           chomp( my $body = $self->mime->body );
114 0           $post_params = CGI->new($body)->Vars;
115             }
116              
117 0           my $params = {};
118 0           $self->_add_to_field($params, $_, $post_params->{$_})
119 0           for keys %{$post_params};
120 0           $self->_add_to_field($params, $_, $query_params->{$_})
121 0           for keys %{$query_params};
122 0           $self->params($params);
123             }
124              
125             sub _add_to_field {
126 0     0     my ($self, $hash, $name, @content) = @_;
127 0           my $field = $hash->{$name};
128 0 0 0       @content = @{$content[0]} if @content && ref($content[0]);
  0            
129 0           @content = map split(/\0/), @content;
130              
131 0 0         if ( defined $field ) {
132 0 0         if ( ref($field) ) {
133 0           push @{$field}, @content;
  0            
134             } else {
135 0           $field = [ $field, @content ];
136             }
137             } else {
138 0 0         if ( @content > 1 ) {
139 0           $field = \@content;
140             } else {
141 0           $field = $content[0];
142             }
143             }
144 0           $hash->{$name} = $field;
145             }
146              
147             1;
148              
149             __END__
150              
151             =head1 SEE ALSO
152              
153             C<HTTP::Daemon>,
154             L<HTTP::Request>,
155             L<Email::MIME>,
156             L<CGI>,
157             L<perl>.
158              
159             =head1 AUTHOR
160              
161             Casey West, <F<casey@geeknest.com>>.
162              
163             =head1 COPYRIGHT
164              
165             Copyright (c) 2005 Casey West. All rights reserved.
166             This module is free software; you can redistribute it and/or modify it
167             under the same terms as Perl itself.
168              
169             =cut