1package Dancer2::Core::Response::Delayed; 2# ABSTRACT: Delayed responses 3$Dancer2::Core::Response::Delayed::VERSION = '0.301004'; 4use Moo; 5use Dancer2::Core::Types qw<CodeRef InstanceOf>; 6 7has request => ( 8 is => 'ro', 9 isa => InstanceOf['Dancer2::Core::Request'], 10 required => 1, 11); 12 13has response => ( 14 is => 'ro', 15 isa => InstanceOf['Dancer2::Core::Response'], 16 required => 1, 17 handles => [qw/status headers push_header/], 18); 19 20has cb => ( 21 is => 'ro', 22 isa => CodeRef, 23 required => 1, 24); 25 26has error_cb => ( 27 is => 'ro', 28 isa => CodeRef, 29 predicate => '_has_error_cb', 30); 31 32sub is_halted() {0} 33sub has_passed() {0} 34 35sub to_psgi { 36 my $self = shift; 37 38 return sub { 39 my $responder = shift; 40 41 local $Dancer2::Core::Route::REQUEST = $self->request; 42 local $Dancer2::Core::Route::RESPONSE = $self->response; 43 local $Dancer2::Core::Route::RESPONDER = $responder; 44 local $Dancer2::Core::Route::WRITER; 45 46 local $Dancer2::Core::Route::ERROR_HANDLER = 47 $self->_has_error_cb ? $self->error_cb : undef; 48 49 $self->cb->(); 50 }; 51} 52 531; 54 55__END__ 56 57=pod 58 59=encoding UTF-8 60 61=head1 NAME 62 63Dancer2::Core::Response::Delayed - Delayed responses 64 65=head1 VERSION 66 67version 0.301004 68 69=head1 SYNOPSIS 70 71 my $response = Dancer2::Core::Response::Delayed->new( 72 request => Dancer2::Core::Request->new(...), 73 response => Dancer2::Core::Response->new(...), 74 cb => sub {...}, 75 76 # optional error handling 77 error_cb => sub { 78 my ($error) = @_; 79 ... 80 }, 81 ); 82 83 # or in an app 84 get '/' => sub { 85 # delayed response: 86 delayed { 87 # streaming content 88 content "data"; 89 content "more data"; 90 91 # close user connection 92 done; 93 } on_error => sub { 94 my ($error) = @_; 95 warning 'Failed to stream to user: ' . request->remote_address; 96 }; 97 }; 98 99=head1 DESCRIPTION 100 101This object represents a delayed (asynchronous) response for L<Dancer2>. 102It can be used via the C<delayed> keyword. 103 104It keeps references to a request and a response in order to avoid 105keeping a reference to the application. 106 107=head1 ATTRIBUTES 108 109=head2 request 110 111Contains a request the delayed response uses. 112 113In the context of a web request, this will be the request that existed 114when the delayed response has been created. 115 116=head2 response 117 118Contains a response the delayed response uses. 119 120In the context of a web request, this will be the response that existed 121when the delayed response has been created. 122 123=head2 cb 124 125The code that will be run asynchronously. 126 127=head2 error_cb 128 129A callback for handling errors. This callback receives the error as its 130first (and currently only) parameter. 131 132=head1 METHODS 133 134=head2 is_halted 135 136A method indicating whether the response has halted. 137 138This is useless in the context of an asynchronous request so it simply 139returns no. 140 141This method is likely going away. 142 143=head2 has_passed 144 145A method indicating whether the response asked to skip the current 146response. 147 148This is useless in the context of an asynchronous request so it simply 149returns no. 150 151This method is likely going away. 152 153=head2 to_psgi 154 155Create a PSGI response. The way it works is by returning a proper PSGI 156response subroutine which localizes the request and response (in case 157the callback wants to edit them without a reference to them), and then 158calls the callback. 159 160Finally, when the callback is done, it asks the response (whether it 161was changed or not) to create its own PSGI response (calling C<to_psgi>) 162and sends that to the callback it receives as a delayed response. 163 164=head1 AUTHOR 165 166Dancer Core Developers 167 168=head1 COPYRIGHT AND LICENSE 169 170This software is copyright (c) 2021 by Alexis Sukrieh. 171 172This is free software; you can redistribute it and/or modify it under 173the same terms as the Perl 5 programming language system itself. 174 175=cut 176