AxKit2
view release on metacpan or search on metacpan
lib/AxKit2/HTTPHeaders.pm view on Meta::CPAN
elsif ($lame) {
$self->{requestLine} = (shift @lines) || "";
$self->{requestLine} =~ /^GET ([^ ]+)$/m
|| die "Strange program interaction - not a lame request at all";
$self->{method} = 'GET';
$self->{uri} = $1;
$self->{ver} = "0.9";
$self->{vernum} = 9;
}
else {
$self->{requestLine} = (shift @lines) || "";
# check for valid request line
return fail("Bogus request line") unless
$self->{requestLine} =~ m!^(\w+) ((?:\*|(?:\S*?)))(?: HTTP/(\d+)\.(\d+))$!;
$self->{method} = $1;
$self->{uri} = $2;
my ($ver_ma, $ver_mi) = ($3, $4);
# now check uri for not being a uri
if ($self->{uri} =~ m!^http://([^/:]+?)(?::\d+)?(/.*)?$!) {
$absoluteURIHost = lc($1);
$self->{uri} = $2 || "/"; # "http://www.foo.com" yields no path, so default to "/"
}
$self->parse_uri;
# default to HTTP/0.9
unless (defined $ver_ma) {
($ver_ma, $ver_mi) = (0, 9);
}
$self->{ver} = "$ver_ma.$ver_mi";
$self->{vernum} = $ver_ma*1000 + $ver_mi;
}
my $last_header = undef;
foreach my $line (@lines) {
if ($line =~ /^\s/) {
next unless defined $last_header;
$self->{headers}{$last_header} .= $line;
} elsif ($line =~ /^([^\x00-\x20\x7f()<>@,;:\\\"\/\[\]?={}]+):\s*(.*)$/) {
# RFC 2616:
# sec 4.2:
# message-header = field-name ":" [ field-value ]
# field-name = token
# sec 2.2:
# token = 1*<any CHAR except CTLs or separators>
$last_header = lc($1);
if (defined $self->{headers}{$last_header}) {
if ($last_header eq "set-cookie") {
# cookie spec doesn't allow merged headers for set-cookie,
# so instead we do this hack so to_string below does the right
# thing without needing to be arrayref-aware or such. also
# this lets client code still modify/delete this data
# (but retrieving the value of "set-cookie" will be broken)
$self->{headers}{$last_header} .= "\r\nSet-Cookie: $2";
} else {
# normal merged header case (according to spec)
$self->{headers}{$last_header} .= ", $2";
}
} else {
$self->{headers}{$last_header} = $2;
$self->{origcase}{$last_header} = $1;
push @{$self->{hdorder}}, $last_header;
}
} else {
return fail("unknown header line");
}
}
# override the host header if an absolute URI was provided
$self->header('Host', $absoluteURIHost)
if defined $absoluteURIHost;
# now error if no host
return fail("HTTP 1.1 requires host header")
if !$is_response && $self->{vernum} >= 1001 && !$self->header('Host');
return $self;
}
=head2 C<< CLASS->new_response( [ CODE ] ) >>
Create a new response header with response code C<CODE> (default: 200 "OK").
Assumes response is HTTP/1.0.
=cut
sub new_response {
my AxKit2::HTTPHeaders $self = shift;
$self = fields::new($self) unless ref $self;
my $code = shift || 200;
$self->{headers} = {};
$self->{origcase} = {};
$self->{hdorder} = [];
$self->{method} = undef;
$self->{uri} = undef;
$self->{responseLine} = "HTTP/1.0 $code " . $self->http_code_english($code);
$self->{code} = $code;
$self->{type} = "res";
$self->{vernum} = 1000;
return $self;
}
=head2 C<< $obj->parse_uri >>
Parse the request URI for querystring parameters.
=cut
sub parse_uri {
lib/AxKit2/HTTPHeaders.pm view on Meta::CPAN
return $self->http_code_english;
}
=head2 C<< $obj->code( CODE [, TEXT] ) >>
Sets the response code to C<CODE> with optional C<TEXT>.
=cut
sub code {
my AxKit2::HTTPHeaders $self = shift;
my ($code, $text) = @_;
$self->{codetext} = $text;
if (! defined $self->{code} || $code != $self->{code}) {
$self->{code} = $code+0;
if ($self->{responseLine}) {
$self->{responseLine} = "HTTP/1.0 $code " . $self->http_code_english;
}
}
}
=head2 C<< $obj->response_code >>
Gets the response code.
=cut
sub response_code {
my AxKit2::HTTPHeaders $self = $_[0];
return $self->{code};
}
=head2 C<< $obj->request_method >>
Gets the request method (e.g. "GET", "POST", etc).
=cut
sub request_method {
my AxKit2::HTTPHeaders $self = shift;
return $self->{method};
}
=head2 C<< $obj->request_uri >>
Gets the request URI. Returns the full URI inclusive of query string.
Also callable as C<< $obj->uri >>.
=cut
sub request_uri {
my AxKit2::HTTPHeaders $self = shift;
@_ and $self->{uri} = shift;
return $self->{uri};
}
*uri = \&request_uri;
# Parse the Cookie header.
sub parse_cookies {
my AxKit2::HTTPHeaders $self = shift;
my $raw_cookies = $self->header('Cookie') || '';
$self->{parsed_cookies} = {};
foreach (split(/;\s+/, $raw_cookies)) {
my ($key, $value) = split("=", $_, 2);
my (@values) = map { uri_decode($_) } split(/&/, $value);
$key = uri_decode($key);
$self->{parsed_cookies}{$key} = \@values;
}
}
# From RFC-2109
# cookie-av = "Comment" "=" value
# | "Domain" "=" value
# | "Max-Age" "=" value
# | "Path" "=" value
# | "Secure"
# | "Version" "=" 1*DIGIT
=head2 C<< $obj->cookie( NAME ) >>
Returns a list of values for the given cookie C<NAME> in LIST context, or the
last set cookie for the given cookie C<NAME> in scalar context. Only works on request
headers.
=head2 C<< $obj->cookie( NAME, VALUE [, PARAMS] ) >>
Set the cookie called C<NAME> with value C<VALUE>.
If value is an arrayref sets a multi-valued cookie.
Optional params are key-value pairs as per the cookie spec, e.g.:
$header->cookie( foo => "bar", path => "/", secure => 1 );
Expiration via C<expires> is not parsed and does not take formats such as "+1d".
It is suggested to use C<max-age> instead (as per RFC 2109) which is a timeout in
seconds from the current time.
=cut
sub cookie {
my AxKit2::HTTPHeaders $self = shift;
my $name = shift;
if (@_) {
die "Cannot set cookies in the request"
if $self->{type} eq 'req';
# set cookie
my $value = shift;
my %params = @_;
# special case for "secure"
my @params = delete($params{secure}) ? ("secure") : ();
# rest are key-value pairs
push @params, map { "$_=$params{$_}" } keys %params;
my $key = uri_encode($name);
my $cookie = "$key=" . join("&", map uri_encode($_), ref($value) ? @$value : $value);
$cookie = join('; ', $cookie, @params);
if (my $oldcookie = $self->header('Set-Cookie')) {
$cookie = "$oldcookie, $cookie";
}
$self->header('Set-Cookie', $cookie);
$self->header('Expires', http_date(0)) unless $self->header('Expires');
return;
}
die "Cannot extract cookies from the response"
if $self->{type} eq 'res';
$self->parse_cookies unless $self->{parsed_cookies};
if (exists $self->{parsed_cookies}{$name}) {
return wantarray ? @{$self->{parsed_cookies}{$name}} : $self->{parsed_cookies}{$name}[-1];
}
}
=head2 C<< $obj->filename( [ STRING ] ) >>
Gets/Sets the request filename value.
=cut
sub filename {
my AxKit2::HTTPHeaders $self = shift;
@_ and $self->{file} = shift;
return $self->{file};
}
=head2 C<< $obj->mime_type( [ STRING ] ) >>
Gets/Sets the request MIME type.
=cut
sub mime_type {
my AxKit2::HTTPHeaders $self = shift;
@_ and $self->{mime_type} = shift;
return $self->{mime_type};
}
=head2 C<< $obj->path_info( [ STRING ] ) >>
Gets/Sets the request path-info value.
=cut
sub path_info {
my AxKit2::HTTPHeaders $self = shift;
@_ and $self->{path_info} = shift;
return $self->{path_info};
}
=head2 C<< $obj->version_number( [ VER ] ) >>
Gets/Sets the header version number. Uses the form C<MAJOR * 1000 + MINOR>, so
HTTP/1.0 will return C<1000> and HTTP/0.9 will return C<9>.
=cut
sub version_number {
my AxKit2::HTTPHeaders $self = shift;
@_ and $self->{vernum} = shift;
$self->{vernum};
}
=head2 C<< $obj->request_line >>
Returns the very first line of the request as seen.
( run in 0.858 second using v1.01-cache-2.11-cpan-39bf76dae61 )