Move actual reading into request
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Request.pm
CommitLineData
fc7ec1d9 1package Catalyst::Request;
2
b4ca0ee8 3use IO::Socket qw[AF_INET inet_aton];
bd917b94 4use Carp;
fc42a730 5use utf8;
de19de2e 6use URI::http;
7use URI::https;
e669e88a 8use URI::QueryParam;
6680c772 9use HTTP::Headers;
b4ca0ee8 10
059c085b 11use Moose;
12
6802c884 13use namespace::clean -except => 'meta';
14
b99ff5d8 15with 'MooseX::Emulate::Class::Accessor::Fast';
16
faa02805 17has env => (is => 'ro', writer => '_set_env');
18
19has _read_position => ( is => 'rw', default => 0 );
20has _read_length => ( is => 'ro',
21 default => sub {
22 my $self = shift;
23 $self->header('Content-Length') || 0;
24 },
25 lazy => 1,
26);
27
5fb12dbb 28has action => (is => 'rw');
29has address => (is => 'rw');
30has arguments => (is => 'rw', default => sub { [] });
31has cookies => (is => 'rw', default => sub { {} });
32has query_keywords => (is => 'rw');
33has match => (is => 'rw');
34has method => (is => 'rw');
35has protocol => (is => 'rw');
059c085b 36has query_parameters => (is => 'rw', default => sub { {} });
5fb12dbb 37has secure => (is => 'rw', default => 0);
38has captures => (is => 'rw', default => sub { [] });
6cb9e383 39has uri => (is => 'rw', predicate => 'has_uri');
8026359e 40has remote_user => (is => 'rw');
5fb12dbb 41has headers => (
e5ecd5bc 42 is => 'rw',
059c085b 43 isa => 'HTTP::Headers',
44 handles => [qw(content_encoding content_length content_type header referer user_agent)],
6680c772 45 default => sub { HTTP::Headers->new() },
46 required => 1,
47 lazy => 1,
059c085b 48);
49
50has _context => (
51 is => 'rw',
52 weak_ref => 1,
02570318 53 clearer => '_clear_context',
059c085b 54);
55
f083854e 56# Amount of data to read from input on each pass
57our $CHUNKSIZE = 64 * 1024;
58
59sub read {
60 my ($self, $maxlength) = @_;
61 my $remaining = $self->_read_length - $self->_read_position;
62 $maxlength ||= $CHUNKSIZE;
63
64 # Are we done reading?
65 if ( $remaining <= 0 ) {
66 return;
67 }
68
69 my $readlen = ( $remaining > $maxlength ) ? $maxlength : $remaining;
70 my $rc = $self->read_chunk( my $buffer, $readlen );
71 if ( defined $rc ) {
72 if (0 == $rc) { # Nothing more to read even though Content-Length
73 # said there should be.
74 return;
75 }
76 $self->_read_position( $self->_read_position + $rc );
77 return $buffer;
78 }
79 else {
80 Catalyst::Exception->throw(
81 message => "Unknown error reading input: $!" );
82 }
83}
84
87f50436 85sub read_chunk {
86 my $self = shift;
87 return $self->env->{'psgi.input'}->read(@_);
88}
89
059c085b 90has body_parameters => (
5fb12dbb 91 is => 'rw',
92 required => 1,
93 lazy => 1,
94 default => sub { {} },
fc7ec1d9 95);
96
059c085b 97has uploads => (
5fb12dbb 98 is => 'rw',
99 required => 1,
5fb12dbb 100 default => sub { {} },
059c085b 101);
102
059c085b 103has parameters => (
104 is => 'rw',
105 required => 1,
106 lazy => 1,
107 default => sub { {} },
108);
109
341620d5 110# TODO:
111# - Can we lose the before modifiers which just call prepare_body ?
112# they are wasteful, slow us down and feel cluttery.
113
114# Can we make _body an attribute, have the rest of
115# these lazy build from there and kill all the direct hash access
116# in Catalyst.pm and Engine.pm?
117
118before $_ => sub {
119 my ($self) = @_;
120 my $context = $self->_context || return;
121 $context->prepare_body;
122} for qw/parameters body_parameters/;
123
e99ec2dc 124around parameters => sub {
125 my ($orig, $self, $params) = @_;
126 if ($params) {
127 if ( !ref $params ) {
128 $self->_context->log->warn(
129 "Attempt to retrieve '$params' with req->params(), " .
130 "you probably meant to call req->param('$params')"
131 );
132 $params = undef;
133 }
134 return $self->$orig($params);
135 }
136 $self->$orig();
059c085b 137};
138
139has base => (
5fb12dbb 140 is => 'rw',
141 required => 1,
142 lazy => 1,
143 default => sub {
059c085b 144 my $self = shift;
6cb9e383 145 return $self->path if $self->has_uri;
059c085b 146 },
147);
148
069355da 149has _body => (
0f56bbcf 150 is => 'rw', clearer => '_clear_body', predicate => '_has_body',
059c085b 151);
610bc6ec 152# Eugh, ugly. Should just be able to rename accessor methods to 'body'
b0ad47c1 153# and provide a custom reader..
610bc6ec 154sub body {
155 my $self = shift;
059c085b 156 $self->_context->prepare_body();
14c057aa 157 croak 'body is a reader' if scalar @_;
610bc6ec 158 return blessed $self->_body ? $self->_body->body : $self->_body;
159}
059c085b 160
161has hostname => (
162 is => 'rw',
163 required => 1,
164 lazy => 1,
165 default => sub {
166 my ($self) = @_;
9fb936e5 167 gethostbyaddr( inet_aton( $self->address ), AF_INET ) || $self->address
059c085b 168 },
169);
170
02570318 171has _path => ( is => 'rw', predicate => '_has_path', clearer => '_clear_path' );
172
8026359e 173# XXX: Deprecated in docs ages ago (2006), deprecated with warning in 5.8000 due
174# to confusion between Engines and Plugin::Authentication. Remove in 5.8100?
175has user => (is => 'rw');
176
059c085b 177sub args { shift->arguments(@_) }
178sub body_params { shift->body_parameters(@_) }
179sub input { shift->body(@_) }
180sub params { shift->parameters(@_) }
181sub query_params { shift->query_parameters(@_) }
182sub path_info { shift->path(@_) }
183sub snippets { shift->captures(@_) }
f7e4e231 184
965f3e35 185=for stopwords param params
186
fc7ec1d9 187=head1 NAME
188
3e19f4f6 189Catalyst::Request - provides information about the current client request
fc7ec1d9 190
191=head1 SYNOPSIS
192
b22c6668 193 $req = $c->request;
194 $req->action;
195 $req->address;
b22c6668 196 $req->arguments;
3e19f4f6 197 $req->args;
b22c6668 198 $req->base;
06e1b616 199 $req->body;
fbcc39ad 200 $req->body_parameters;
b5176d9e 201 $req->content_encoding;
202 $req->content_length;
203 $req->content_type;
b77e7869 204 $req->cookie;
b22c6668 205 $req->cookies;
b5176d9e 206 $req->header;
b22c6668 207 $req->headers;
208 $req->hostname;
61bacdcc 209 $req->input;
3b4d1251 210 $req->query_keywords;
b22c6668 211 $req->match;
212 $req->method;
e7c0c583 213 $req->param;
e7c0c583 214 $req->parameters;
3e19f4f6 215 $req->params;
b22c6668 216 $req->path;
bfde09a2 217 $req->protocol;
fbcc39ad 218 $req->query_parameters;
219 $req->read;
b5176d9e 220 $req->referer;
bfde09a2 221 $req->secure;
2982e768 222 $req->captures; # previously knows as snippets
e7c0c583 223 $req->upload;
b22c6668 224 $req->uploads;
77d12cae 225 $req->uri;
7ce7ca2e 226 $req->user;
66294129 227 $req->user_agent;
b22c6668 228
3e22baa5 229See also L<Catalyst>, L<Catalyst::Request::Upload>.
fc7ec1d9 230
231=head1 DESCRIPTION
232
3e19f4f6 233This is the Catalyst Request class, which provides an interface to data for the
234current client request. The request object is prepared by L<Catalyst::Engine>,
235thus hiding the details of the particular engine implementation.
b22c6668 236
237=head1 METHODS
fc7ec1d9 238
b5ecfcf0 239=head2 $req->action
fc7ec1d9 240
aae8d418 241[DEPRECATED] Returns the name of the requested action.
242
243
244Use C<< $c->action >> instead (which returns a
245L<Catalyst::Action|Catalyst::Action> object).
fc7ec1d9 246
b5ecfcf0 247=head2 $req->address
0556eb49 248
3e19f4f6 249Returns the IP address of the client.
61b1e958 250
b5ecfcf0 251=head2 $req->arguments
61b1e958 252
b22c6668 253Returns a reference to an array containing the arguments.
fc7ec1d9 254
255 print $c->request->arguments->[0];
256
c436c1e8 257For example, if your action was
258
7d7519a4 259 package MyApp::Controller::Foo;
85d9fce6 260
261 sub moose : Local {
262 ...
263 }
c436c1e8 264
3e19f4f6 265and the URI for the request was C<http://.../foo/moose/bah>, the string C<bah>
c436c1e8 266would be the first and only argument.
267
6d920953 268Arguments get automatically URI-unescaped for you.
8f58057d 269
b5ecfcf0 270=head2 $req->args
3e19f4f6 271
01011731 272Shortcut for L</arguments>.
3e19f4f6 273
b5ecfcf0 274=head2 $req->base
fc7ec1d9 275
328f225e 276Contains the URI base. This will always have a trailing slash. Note that the
f4dda4a8 277URI scheme (e.g., http vs. https) must be determined through heuristics;
328f225e 278depending on your server configuration, it may be incorrect. See $req->secure
279for more info.
c436c1e8 280
3e19f4f6 281If your application was queried with the URI
282C<http://localhost:3000/some/path> then C<base> is C<http://localhost:3000/>.
fc7ec1d9 283
b5ecfcf0 284=head2 $req->body
06e1b616 285
843871cf 286Returns the message body of the request, as returned by L<HTTP::Body>: a string,
287unless Content-Type is C<application/x-www-form-urlencoded>, C<text/xml>, or
288C<multipart/form-data>, in which case a L<File::Temp> object is returned.
e060fe05 289
b5ecfcf0 290=head2 $req->body_parameters
fbcc39ad 291
3e19f4f6 292Returns a reference to a hash containing body (POST) parameters. Values can
fbcc39ad 293be either a scalar or an arrayref containing scalars.
294
295 print $c->request->body_parameters->{field};
296 print $c->request->body_parameters->{field}->[0];
c436c1e8 297
d631b5f9 298These are the parameters from the POST part of the request, if any.
e5ecd5bc 299
b5ecfcf0 300=head2 $req->body_params
fbcc39ad 301
3e19f4f6 302Shortcut for body_parameters.
fbcc39ad 303
b5ecfcf0 304=head2 $req->content_encoding
b5176d9e 305
3e19f4f6 306Shortcut for $req->headers->content_encoding.
b5176d9e 307
b5ecfcf0 308=head2 $req->content_length
b5176d9e 309
3e19f4f6 310Shortcut for $req->headers->content_length.
b5176d9e 311
b5ecfcf0 312=head2 $req->content_type
b5176d9e 313
3e19f4f6 314Shortcut for $req->headers->content_type.
b5176d9e 315
b5ecfcf0 316=head2 $req->cookie
3ad654e0 317
3e19f4f6 318A convenient method to access $req->cookies.
3ad654e0 319
320 $cookie = $c->request->cookie('name');
321 @cookies = $c->request->cookie;
322
323=cut
324
325sub cookie {
326 my $self = shift;
327
328 if ( @_ == 0 ) {
b77e7869 329 return keys %{ $self->cookies };
3ad654e0 330 }
331
332 if ( @_ == 1 ) {
333
334 my $name = shift;
335
b77e7869 336 unless ( exists $self->cookies->{$name} ) {
3ad654e0 337 return undef;
338 }
fbcc39ad 339
b77e7869 340 return $self->cookies->{$name};
3ad654e0 341 }
342}
343
b5ecfcf0 344=head2 $req->cookies
fc7ec1d9 345
b22c6668 346Returns a reference to a hash containing the cookies.
fc7ec1d9 347
348 print $c->request->cookies->{mycookie}->value;
349
7e743798 350The cookies in the hash are indexed by name, and the values are L<CGI::Simple::Cookie>
c436c1e8 351objects.
352
b5ecfcf0 353=head2 $req->header
b5176d9e 354
3e19f4f6 355Shortcut for $req->headers->header.
b5176d9e 356
b5ecfcf0 357=head2 $req->headers
fc7ec1d9 358
3e19f4f6 359Returns an L<HTTP::Headers> object containing the headers for the current request.
fc7ec1d9 360
361 print $c->request->headers->header('X-Catalyst');
362
b5ecfcf0 363=head2 $req->hostname
0556eb49 364
178dca5f 365Returns the hostname of the client. Use C<< $req->uri->host >> to get the hostname of the server.
e5ecd5bc 366
b5ecfcf0 367=head2 $req->input
61bacdcc 368
3e19f4f6 369Alias for $req->body.
61bacdcc 370
3b4d1251 371=head2 $req->query_keywords
372
373Contains the keywords portion of a query string, when no '=' signs are
374present.
375
376 http://localhost/path?some+keywords
b0ad47c1 377
3b4d1251 378 $c->request->query_keywords will contain 'some keywords'
379
b5ecfcf0 380=head2 $req->match
fc7ec1d9 381
3e19f4f6 382This contains the matching part of a Regex action. Otherwise
2c83fd5a 383it returns the same as 'action', except for default actions,
384which return an empty string.
fc7ec1d9 385
b5ecfcf0 386=head2 $req->method
b5176d9e 387
388Contains the request method (C<GET>, C<POST>, C<HEAD>, etc).
389
b5ecfcf0 390=head2 $req->param
e7c0c583 391
b0ad47c1 392Returns GET and POST parameters with a CGI.pm-compatible param method. This
3e19f4f6 393is an alternative method for accessing parameters in $c->req->parameters.
e7c0c583 394
a82c2894 395 $value = $c->request->param( 'foo' );
396 @values = $c->request->param( 'foo' );
e7c0c583 397 @params = $c->request->param;
398
3e705254 399Like L<CGI>, and B<unlike> earlier versions of Catalyst, passing multiple
a82c2894 400arguments to this method, like this:
401
85d9fce6 402 $c->request->param( 'foo', 'bar', 'gorch', 'quxx' );
a82c2894 403
404will set the parameter C<foo> to the multiple values C<bar>, C<gorch> and
405C<quxx>. Previously this would have added C<bar> as another value to C<foo>
3e19f4f6 406(creating it if it didn't exist before), and C<quxx> as another value for
407C<gorch>.
a82c2894 408
83312afd 409B<NOTE> this is considered a legacy interface and care should be taken when
410using it. C<< scalar $c->req->param( 'foo' ) >> will return only the first
411C<foo> param even if multiple are present; C<< $c->req->param( 'foo' ) >> will
412return a list of as many are present, which can have unexpected consequences
413when writing code of the form:
414
415 $foo->bar(
416 a => 'b',
417 baz => $c->req->param( 'baz' ),
418 );
419
420If multiple C<baz> parameters are provided this code might corrupt data or
421cause a hash initialization error. For a more straightforward interface see
422C<< $c->req->parameters >>.
423
e7c0c583 424=cut
425
426sub param {
427 my $self = shift;
428
429 if ( @_ == 0 ) {
430 return keys %{ $self->parameters };
431 }
432
bfde09a2 433 if ( @_ == 1 ) {
e7c0c583 434
bfde09a2 435 my $param = shift;
6bd2b72c 436
bfde09a2 437 unless ( exists $self->parameters->{$param} ) {
438 return wantarray ? () : undef;
439 }
440
441 if ( ref $self->parameters->{$param} eq 'ARRAY' ) {
442 return (wantarray)
443 ? @{ $self->parameters->{$param} }
444 : $self->parameters->{$param}->[0];
445 }
446 else {
447 return (wantarray)
448 ? ( $self->parameters->{$param} )
449 : $self->parameters->{$param};
450 }
d7945f32 451 }
a82c2894 452 elsif ( @_ > 1 ) {
453 my $field = shift;
454 $self->parameters->{$field} = [@_];
d7945f32 455 }
e7c0c583 456}
b5176d9e 457
b5ecfcf0 458=head2 $req->parameters
61b1e958 459
3e19f4f6 460Returns a reference to a hash containing GET and POST parameters. Values can
d08ced28 461be either a scalar or an arrayref containing scalars.
fc7ec1d9 462
e7c0c583 463 print $c->request->parameters->{field};
464 print $c->request->parameters->{field}->[0];
fc7ec1d9 465
c436c1e8 466This is the combination of C<query_parameters> and C<body_parameters>.
467
b5ecfcf0 468=head2 $req->params
3e19f4f6 469
470Shortcut for $req->parameters.
471
b5ecfcf0 472=head2 $req->path
fc7ec1d9 473
3e19f4f6 474Returns the path, i.e. the part of the URI after $req->base, for the current request.
fc7ec1d9 475
be6801fa 476 http://localhost/path/foo
477
478 $c->request->path will contain 'path/foo'
479
b5ecfcf0 480=head2 $req->path_info
fbcc39ad 481
10011c19 482Alias for path, added for compatibility with L<CGI>.
fbcc39ad 483
484=cut
485
486sub path {
02fb5d78 487 my ( $self, @params ) = @_;
4f5ebacd 488
02fb5d78 489 if (@params) {
490 $self->uri->path(@params);
02570318 491 $self->_clear_path;
fbcc39ad 492 }
02570318 493 elsif ( $self->_has_path ) {
494 return $self->_path;
e561386f 495 }
02fb5d78 496 else {
497 my $path = $self->uri->path;
498 my $location = $self->base->path;
499 $path =~ s/^(\Q$location\E)?//;
500 $path =~ s/^\///;
02570318 501 $self->_path($path);
fbcc39ad 502
02fb5d78 503 return $path;
504 }
fbcc39ad 505}
506
b5ecfcf0 507=head2 $req->protocol
bfde09a2 508
3e19f4f6 509Returns the protocol (HTTP/1.0 or HTTP/1.1) used for the current request.
bfde09a2 510
b5ecfcf0 511=head2 $req->query_parameters
fbcc39ad 512
def54ce2 513=head2 $req->query_params
514
3e19f4f6 515Returns a reference to a hash containing query string (GET) parameters. Values can
fbcc39ad 516be either a scalar or an arrayref containing scalars.
517
518 print $c->request->query_parameters->{field};
519 print $c->request->query_parameters->{field}->[0];
b0ad47c1 520
b5ecfcf0 521=head2 $req->read( [$maxlength] )
fbcc39ad 522
3e19f4f6 523Reads a chunk of data from the request body. This method is intended to be
524used in a while loop, reading $maxlength bytes on every call. $maxlength
fbcc39ad 525defaults to the size of the request if not specified.
526
87f50436 527=head2 $req->read_chunk(\$buff, $max)
528
529Reads a chunk..
530
9779c885 531You have to set MyApp->config(parse_on_demand => 1) to use this directly.
fbcc39ad 532
b5ecfcf0 533=head2 $req->referer
fc7ec1d9 534
3e19f4f6 535Shortcut for $req->headers->referer. Returns the referring page.
fc7ec1d9 536
b5ecfcf0 537=head2 $req->secure
bfde09a2 538
328f225e 539Returns true or false, indicating whether the connection is secure
f4dda4a8 540(https). Note that the URI scheme (e.g., http vs. https) must be determined
ae7da8f5 541through heuristics, and therefore the reliability of $req->secure will depend
328f225e 542on your server configuration. If you are serving secure pages on the standard
543SSL port (443) and/or setting the HTTPS environment variable, $req->secure
544should be valid.
bfde09a2 545
2982e768 546=head2 $req->captures
547
5c6a56e0 548Returns a reference to an array containing captured args from chained
549actions or regex captures.
fc7ec1d9 550
2982e768 551 my @captures = @{ $c->request->captures };
552
553=head2 $req->snippets
fc7ec1d9 554
10011c19 555C<captures> used to be called snippets. This is still available for backwards
2982e768 556compatibility, but is considered deprecated.
fc7ec1d9 557
b5ecfcf0 558=head2 $req->upload
e7c0c583 559
3e19f4f6 560A convenient method to access $req->uploads.
e7c0c583 561
562 $upload = $c->request->upload('field');
563 @uploads = $c->request->upload('field');
564 @fields = $c->request->upload;
bfde09a2 565
e7c0c583 566 for my $upload ( $c->request->upload('field') ) {
146554c5 567 print $upload->filename;
e7c0c583 568 }
569
570=cut
571
572sub upload {
573 my $self = shift;
574
575 if ( @_ == 0 ) {
576 return keys %{ $self->uploads };
577 }
578
bfde09a2 579 if ( @_ == 1 ) {
e7c0c583 580
bfde09a2 581 my $upload = shift;
582
583 unless ( exists $self->uploads->{$upload} ) {
584 return wantarray ? () : undef;
585 }
6bd2b72c 586
bfde09a2 587 if ( ref $self->uploads->{$upload} eq 'ARRAY' ) {
588 return (wantarray)
589 ? @{ $self->uploads->{$upload} }
590 : $self->uploads->{$upload}->[0];
591 }
592 else {
593 return (wantarray)
fbcc39ad 594 ? ( $self->uploads->{$upload} )
595 : $self->uploads->{$upload};
bfde09a2 596 }
d7945f32 597 }
bfde09a2 598
a4f5c51e 599 if ( @_ > 1 ) {
bfde09a2 600
601 while ( my ( $field, $upload ) = splice( @_, 0, 2 ) ) {
602
603 if ( exists $self->uploads->{$field} ) {
604 for ( $self->uploads->{$field} ) {
605 $_ = [$_] unless ref($_) eq "ARRAY";
606 push( @$_, $upload );
607 }
608 }
609 else {
610 $self->uploads->{$field} = $upload;
611 }
612 }
e7c0c583 613 }
614}
615
b5ecfcf0 616=head2 $req->uploads
fc7ec1d9 617
bfde09a2 618Returns a reference to a hash containing uploads. Values can be either a
b0ad47c1 619L<Catalyst::Request::Upload> object, or an arrayref of
84e7aa89 620L<Catalyst::Request::Upload> objects.
e7c0c583 621
622 my $upload = $c->request->uploads->{field};
623 my $upload = $c->request->uploads->{field}->[0];
624
b5ecfcf0 625=head2 $req->uri
fbcc39ad 626
d26ee0d0 627Returns a L<URI> object for the current request. Stringifies to the URI text.
fbcc39ad 628
a375a206 629=head2 $req->mangle_params( { key => 'value' }, $appendmode);
bd917b94 630
a375a206 631Returns a hashref of parameters stemming from the current request's params,
632plus the ones supplied. Keys for which no current param exists will be
633added, keys with undefined values will be removed and keys with existing
634params will be replaced. Note that you can supply a true value as the final
635argument to change behavior with regards to existing parameters, appending
636values rather than replacing them.
637
638A quick example:
639
640 # URI query params foo=1
641 my $hashref = $req->mangle_params({ foo => 2 });
642 # Result is query params of foo=2
643
644versus append mode:
645
646 # URI query params foo=1
647 my $hashref = $req->mangle_params({ foo => 2 }, 1);
648 # Result is query params of foo=1&foo=2
649
650This is the code behind C<uri_with>.
bd917b94 651
652=cut
653
a375a206 654sub mangle_params {
655 my ($self, $args, $append) = @_;
b0ad47c1 656
a375a206 657 carp('No arguments passed to mangle_params()') unless $args;
fbb513f7 658
2f381252 659 foreach my $value ( values %$args ) {
d0f0fcf6 660 next unless defined $value;
fbb513f7 661 for ( ref $value eq 'ARRAY' ? @$value : $value ) {
662 $_ = "$_";
7066a4d5 663 utf8::encode( $_ ) if utf8::is_utf8($_);
fc42a730 664 }
fc42a730 665 };
b0ad47c1 666
a375a206 667 my %params = %{ $self->uri->query_form_hash };
668 foreach my $key (keys %{ $args }) {
669 my $val = $args->{$key};
670 if(defined($val)) {
671
672 if($append && exists($params{$key})) {
673
674 # This little bit of heaven handles appending a new value onto
675 # an existing one regardless if the existing value is an array
676 # or not, and regardless if the new value is an array or not
677 $params{$key} = [
678 ref($params{$key}) eq 'ARRAY' ? @{ $params{$key} } : $params{$key},
679 ref($val) eq 'ARRAY' ? @{ $val } : $val
680 ];
681
682 } else {
683 $params{$key} = $val;
684 }
685 } else {
686
687 # If the param wasn't defined then we delete it.
688 delete($params{$key});
689 }
690 }
691
692
693 return \%params;
694}
695
696=head2 $req->uri_with( { key => 'value' } );
697
698Returns a rewritten URI object for the current request. Key/value pairs
699passed in will override existing parameters. You can remove an existing
700parameter by passing in an undef value. Unmodified pairs will be
701preserved.
702
703You may also pass an optional second parameter that puts C<uri_with> into
704append mode:
705
706 $req->uri_with( { key => 'value' }, { mode => 'append' } );
9779c885 707
a375a206 708See C<mangle_params> for an explanation of this behavior.
709
710=cut
711
712sub uri_with {
713 my( $self, $args, $behavior) = @_;
714
715 carp( 'No arguments passed to uri_with()' ) unless $args;
716
717 my $append = 0;
718 if((ref($behavior) eq 'HASH') && defined($behavior->{mode}) && ($behavior->{mode} eq 'append')) {
719 $append = 1;
720 }
721
722 my $params = $self->mangle_params($args, $append);
723
724 my $uri = $self->uri->clone;
725 $uri->query_form($params);
2f381252 726
bd917b94 727 return $uri;
728}
729
8026359e 730=head2 $req->remote_user
731
732Returns the value of the C<REMOTE_USER> environment variable.
7ce7ca2e 733
b5ecfcf0 734=head2 $req->user_agent
b5176d9e 735
3e19f4f6 736Shortcut to $req->headers->user_agent. Returns the user agent (browser)
737version string.
b5176d9e 738
059c085b 739=head2 meta
740
741Provided by Moose
742
3e19f4f6 743=head1 AUTHORS
fc7ec1d9 744
2f381252 745Catalyst Contributors, see Catalyst.pm
fc7ec1d9 746
747=head1 COPYRIGHT
748
536bee89 749This library is free software. You can redistribute it and/or modify
61b1e958 750it under the same terms as Perl itself.
fc7ec1d9 751
752=cut
753
e5ecd5bc 754__PACKAGE__->meta->make_immutable;
755
fc7ec1d9 7561;