Dancer2
    
    
  
  
  
view release on metacpan or search on metacpan
    * GH #916: Fix test example. (Peter Mottram - @SysPete)
    * GH #912, #913: Fix documentation on when stacks are printed.
      (Andrew Solomon)
0.160001  2015-05-14 20:40:10+02:00 Europe/Amsterdam
    [ BUG FIXES ]
    * GH #893, #895: Catch config parse errors when Config::Any doesn't throw
      them. (Russell Jenkins)
    * GH #899: Minimum YAML version supported is v0.86 (Shlomi Fish)
    * GH #906: send_file - missing import and fix logic error for streaming
      by default (Russell Jenkins)
    [ DOCUMENTATION ]
    * GH #897: Remove docs for unimplemented 'load' keyword (Fayland Lam)
    [ ENHANCEMENT ]
    * GH #894, #898: Add status and headers methods to ::Response::Delayed
      (Yanick Champoux, Charlie Gonzalez)
0.160000  2015-04-27 00:12:55+02:00 Europe/Amsterdam
    [ BUG FIXES ]
    * GH #856: Memory leak when throwing exception from a hook. (Sawyer X)
0.159001  2015-02-25 15:31:35+01:00 Europe/Amsterdam
    [ BUG FIXES ]
    * GH #855: Ensure Dancer2::Test is compatible with Pod::Simple 3.30.
      (Russell Jenkins)
    [ DOCUMENTATION ]
    * Add an example for delayed (async) streaming response. (Sawyer X)
    * Small link fix. (Sawyer X)
0.159000  2015-02-24 04:51:20+01:00 Europe/Amsterdam
    [ BUG FIXES ]
    * GH #762: Delay app cleanup until errors are rendered. (Russell Jenkins)
    * GH #835: Correct Logic error in Logger if no request exists.
               (Lennart Hengstmengel)
    * GH #839: Correct "no_server_tokens" definition in production.yml.
               (Nikita K)
lib/Dancer2/Core/App.pm view on Meta::CPAN
    ( exists $options{'charset'} ) and $charset = $options{'charset'};
    $content_type .= "; charset=$charset" if $content_type and $charset;
    ( defined $content_type )
      and $self->response->header('Content-Type' => $content_type );
    # content disposition
    ( exists $options{filename} )
      and $self->response->header( 'Content-Disposition' =>
          ($options{content_disposition} || "attachment") . "; filename=\"$options{filename}\"" );
    # use a delayed response unless server does not support streaming
    my $use_streaming = exists $options{streaming} ? $options{streaming} : 1;
    my $response;
    my $env = $self->request->env;
    if ( $env->{'psgi.streaming'} && $use_streaming ) {
        my $cb = sub {
            my $responder = $Dancer2::Core::Route::RESPONDER;
            my $res = $Dancer2::Core::Route::RESPONSE;
            return $responder->(
                [ $res->status, $res->headers_to_array, $fh ]
            );
        };
        Scalar::Util::weaken( my $weak_self = $self );
lib/Dancer2/Core/DSL.pm view on Meta::CPAN
        local $Dancer2::Core::Route::RESPONDER     = $responder;
        local $Dancer2::Core::Route::WRITER        = $writer;
        local $Dancer2::Core::Route::ERROR_HANDLER = $handler;
        $cb->(@_);
    };
}
sub flush {
    my $responder = $Dancer2::Core::Route::RESPONDER
        or croak 'flush() called outside streaming response';
    my $response = $Dancer2::Core::Route::RESPONSE;
    $Dancer2::Core::Route::WRITER = $responder->([
        $response->status, $response->headers_to_array,
    ]);
}
sub done {
    my $writer = $Dancer2::Core::Route::WRITER
        or croak 'done() called outside streaming response';
    $writer->close;
}
sub pass         { shift->app->pass }
#
# Route handler helpers
#
lib/Dancer2/Core/Response/Delayed.pm view on Meta::CPAN
        error_cb  => sub {
            my ($error) = @_;
            ...
        },
    );
    # or in an app
    get '/' => sub {
        # delayed response:
        delayed {
            # streaming content
            content "data";
            content "more data";
            # close user connection
            done;
        } on_error => sub {
            my ($error) = @_;
            warning 'Failed to stream to user: ' . request->remote_address;
        };
    };
lib/Dancer2/Manual.pod view on Meta::CPAN
to initiate an asynchronous response, allowing you to deliver long-running
results, or handling long-running operations.
=head2 done
Once everything is set, you can use C<done> to finalize and send the
response to the visitor.
=head2 flush
To send parts of the response incrementally, C<flush> allows streaming
content to the client in a delayed response without closing the connection.
=head2 Example: Asynchronous HTTP Request
Hereâs how you can fetch data asynchronously in Dancer2. Instead of
waiting for a response, the request runs in the background and delivers
the result when itâs ready:
    use Dancer2;
    use Future::HTTP;
lib/Dancer2/Manual/Keywords.pod view on Meta::CPAN
Initiates an asynchronous response. Requires a Plack/PSGI server capable
of serving requests asynchronously.
B<When to use>: When starting an asynchronous reponse.
B<Related Keywords>: L</done>, L</flush>
=head2 L<done|Dancer2::Manual/done>
Finalizes an asynchronous repsonse and closes the connection. Can only
be run within the streaming response callback.
B<When to use>: When finishing delivery of data asynchronously.
B<See also>: L</delayed>, L</flush>
=head2 L<encode_json|Dancer2::Manual/encode_json>
Serializes a data structure to a UTF-8 encoded binary JSON string. Calling
this keyword will not trigger the application's serializer hooks.
B<When to use>: When needing to translate a Perl data structure to JSON.
B<See also>: L</decode_json>, L</to_json>
=head2 L<flush|Dancer2::Manual/flush>
Flushes content headers when streaming a response. This is necessary when
C<content> is called multiple times.
B<When to use>: When streaming large amounts of data (such as video)
asynchronously.
B<See also>: L</delayed>, L</done>
=head2 L<forward|Dancer2::Manual/forward>
Forwards the request to another route handler.
B<When to use>: Internally redirect to another route within the app.
t/dsl/send_file.t view on Meta::CPAN
    };
    get '/check_content_type' => sub {
        my $temp = File::Temp->new();
        print $temp "hello";
        close $temp;
        send_file($temp->filename, content_type => 'image/png',
                                   system_path  => 1);
    };
    get '/no_streaming' => sub {
        my $file = File::Spec->rel2abs(__FILE__);
        send_file( $file, system_path => 1, streaming => 0 );
    };
    get '/options_streaming' => sub {
        my $file = File::Spec->rel2abs(__FILE__);
        send_file( $file, system_path => 1, streaming => 1 );
    };
    get '/content_disposition/attachment' => sub {
        send_file('1x1.png', filename => '1x1.png');
    };
    get '/content_disposition/inline' => sub {
        send_file('1x1.png', filename => '1x1.png', content_disposition => 'inline');
    };
}
t/dsl/send_file.t view on Meta::CPAN
    subtest "filehandles" => sub {
        my $r = $cb->( GET '/filehandle' );
        is( $r->code, 200, 'send_file set status to 200 (filehandle)');
        is( $r->content_type, 'text/plain', 'expected content_type');
        is( $r->content_type_charset, 'UTF-8', 'expected charset');
        like( $r->content, qr{package StaticContent}, 'filehandle content' );
    };
    subtest "no streaming" => sub {
        my $r = $cb->( GET '/no_streaming' ); 
        is( $r->code, 200, 'send_file set status to 200 (no streaming)');
        like( $r->content, qr{package StaticContent}, 'no streaming - content' );
    };
    subtest "options streaming" => sub {
        my $r = $cb->( GET '/options_streaming' ); 
        is( $r->code, 200, 'send_file set status to 200 (options streaming)');
        like( $r->content, qr{package StaticContent}, 'options streaming - content' );
    };
    subtest 'send_file returns correct content type' => sub {
        my $r = $cb->( GET '/check_content_type' );
        ok($r->is_success, 'send_file returns success');
        is($r->content_type, 'image/png', 'send_file returns correct content_type');
    };
    subtest 'Content-Disposition defaults to "attachment"' => sub {
( run in 0.676 second using v1.01-cache-2.11-cpan-5dc5da66d9d )