# This file documents the revision history for Perl extension Catalyst.
+5.80030 2011-01-04 13:13:02
+
New features:
- Add a --proc_title option to the FCGI script to set the process
title.
+ - Allow the response body to be set to `undef' explicitly to indicate the
+ absence of a body. It can be used to indicate that no body should be sent at
+ all and processing of views should be skipped. This is especially useful for
+ things like X-Sendfile, which now no longer require providing fake response
+ bodies to suppress view processing. In order for this to work, you will also
+ have upgrade Catalyst::Action::RenderView to at least version 0.15.
Bug fixes:
- Deal correctly with GLOB file handles in the response body (setting
maximum number of actions). This means that (for example)
a URI path /foo/* made out of 2 actions will take preference
to a URI path /*/* made out of 3 actions. Please check your applications
- if you are using chained action and please write new test to report
+ if you are using chained action and please write new test to report
failing case.
+ - Stop relying on bugs in the pure-perl version of Package::Stash. New
+ versions of Package::Stash load Package::Stash::XS if
+ available. Package::Stash::XS fixes some of the bugs of the pure-perl
+ version, exposing our faulty assumption and breaking things. We now work
+ with both old and new versions of Package::Stash, both with and without
+ Package::Stash::XS being installed. Older versions of Catalyst-Runtime also
+ work with both old and new versions of Package::Stash, but only if
+ Package::Stash::XS is *not* installed.
Documentation:
- Clarify that when forwarding or detaching, the end action associated
'Catalyst::Plugin::ENV' => '9999', # This plugin is just stupid, full stop
# should have been a core fix.
'Catalyst::Plugin::Unicode::Encoding' => '0.2',
+ 'Catalyst::Plugin::Authentication' => '0.10010', # _config accessor in ::Credential::Password
'Catalyst::Authentication::Credential::HTTP' => '1.009',
'Catalyst::Plugin::Session::Store::File' => '0.16',
'Catalyst::Plugin::Session' => '0.21',
# Remember to update this in Catalyst::Runtime as well!
-our $VERSION = '5.80029';
+our $VERSION = '5.80030';
sub import {
my ( $class, @arguments ) = @_;
}
# Content-Length
- if ( $response->body && !$response->content_length ) {
+ if ( defined $response->body && length $response->body && !$response->content_length ) {
# get the length from a filehandle
if ( blessed( $response->body ) && $response->body->can('read') || ref( $response->body ) eq 'GLOB' )
=head2 $c->request_class
-Returns or sets the request class.
+Returns or sets the request class. Defaults to L<Catalyst::Request>.
=head2 $c->response_class
-Returns or sets the response class.
+Returns or sets the response class. Defaults to L<Catalyst::Response>.
=head2 $c->read( [$maxlength] )
# TODO maybe this should be a ClassData option?
my $class = blessed($self) || $self;
my $meta = Class::MOP::get_metaclass_by_name($class);
- unless ($meta->has_package_symbol('$_config')) {
+ unless (${ $meta->get_or_add_package_symbol('$_config') }) {
# Call merge_hashes to ensure we deep copy the parent
# config onto the subclass
$self->_config( Catalyst::Utils::merge_hashes($config, {}) );
$self->_prepared_write(1);
}
- return 0 if !defined $buffer;
+ $buffer = q[] unless defined $buffer;
my $len = length($buffer);
$self->_writer->write($buffer);
with 'MooseX::Emulate::Class::Accessor::Fast';
has cookies => (is => 'rw', default => sub { {} });
-has body => (is => 'rw', default => '', lazy => 1, predicate => 'has_body',
- clearer => '_clear_body'
-);
-after 'body' => sub { # If someone assigned undef, clear the body so we get ''
- if (scalar(@_) == 2 && !defined($_[1])) {
- $_[0]->_clear_body;
- }
-};
+has body => (is => 'rw', default => undef, lazy => 1, predicate => 'has_body');
+
has location => (is => 'rw');
has status => (is => 'rw', default => 200);
has finalized_headers => (is => 'rw', default => 0);
# Remember to update this in Catalyst as well!
-our $VERSION = '5.80029';
+our $VERSION = '5.80030';
=head1 NAME
content_like('/account/123', qr/This is account 123/, 'account');
content_like('/account/profile/007/James Bond', qr/This is profile of James Bond/, 'account');
+TODO: {
+ local $TODO = q(new chained action test case that fails yet.);
+ content_like('/downloads/', qr/This is downloads index/, 'downloads');
+}
+
action_notfound('/c');
done_testing;
--- /dev/null
+#!perl
+
+use strict;
+use warnings;
+
+use FindBin;
+use lib "$FindBin::Bin/../lib";
+
+use Test::More;
+use Catalyst::Test 'TestApp';
+
+# body '0'
+{
+ my $res = request('/zerobody');
+ is $res->content, '0';
+ is $res->header('Content-Length'), '1';
+}
+
+# body ''
+{
+ my $res = request('/emptybody');
+ is $res->content, '';
+ ok !defined $res->header('Content-Length');
+}
+
+done_testing;
+
'Plus is not encoded'
);
+TODO: {
+ local $TODO = 'broken by 5.7008';
+ is(
+ Catalyst::uri_for( $context, '/bar#fragment', { param1 => 'value1' } )->as_string,
+ 'http://127.0.0.1/foo/bar?param1=value1#fragment',
+ 'URI for path with fragment and query params'
+ );
+}
+
# test with utf-8
is(
Catalyst::uri_for( $context, 'quux', { param1 => "\x{2620}" } )->as_string,
use strict;
use warnings;
-use Test::More tests => 6;
+use Test::More;
use_ok('Catalyst::Response');
+use_ok('Catalyst::Engine');
my $res = Catalyst::Response->new;
is($res->status, 500, 'code sets status');
$res->status(501);
is($res->code, 501, 'status sets code');
-is($res->body, '', "default response body ''");
-$res->body(undef);
-is($res->body, '', "response body '' after assigned undef");
+done_testing;
$c->response->body( "This is profile of " . $acc );
}
+=head2 downloads
+
+ This is a different test, this function is void, just to let following in the chain
+ to declare downloads as PathPart.
+
+=cut
+
+sub downloads : Chained('setup') PathPart('') CaptureArgs(0) {
+ my($self,$c) = @_;
+}
+
+sub downloads_index : Chained('downloads') PathPart('downloads') Args(0) {
+ my($self,$c) = @_;
+ $c->response->body( "This is download index");
+}
+
sub default : Chained('setup') PathPart('') Args() {
my ( $self, $c ) = @_;
$c->response->body( 'Page not found' );
$c->forward('TestApp::View::Dump::Request');
}
+sub zerobody : Local {
+ my ($self, $c) = @_;
+ $c->res->body('0');
+}
+
+sub emptybody : Local {
+ my ($self, $c) = @_;
+ $c->res->body('');
+}
+
sub localregex : LocalRegex('^localregex$') {
my ( $self, $c ) = @_;
$c->res->header( 'X-Test-Class' => ref($self) );