File: large_response_example

package info (click to toggle)
libanyevent-httpd-perl 0.93-6
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, forky, sid, trixie
  • size: 244 kB
  • sloc: perl: 1,247; makefile: 4
file content (107 lines) | stat: -rwxr-xr-x 2,682 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#!/opt/perl/bin/perl
use common::sense;
use AnyEvent;
use AnyEvent::HTTPD;
use AnyEvent::AIO;
use IO::AIO;

my $cvar = AnyEvent->condvar;

my $httpd = AnyEvent::HTTPD->new (port => 19090);

my $SEND_FILE = defined $ARGV[0] ? $ARGV[0] : 'bshttp.png';
my $mime = `file -i $SEND_FILE`;
$mime =~ s/^(.*?): //;
$mime =~ s/\r?\n$//;

print "going to send $SEND_FILE: $mime\n";

sub send_file {
   my ($req) = @_;

   my $fh;
   my $last_pos = 0;

   print "going to open $SEND_FILE...\n";

   # use IO::AIO to async open the file
   aio_open $SEND_FILE, O_RDONLY, 0, sub {
      $fh = shift;

      unless ($fh) {
         warn "couldn't open $SEND_FILE: $!\n";
         $data_cb->(); # stop sending data...
         return;
      }

      my $size = -s $fh;

      print "opened $SEND_FILE, $size bytes big!\n";

      # make a reader callback, that will be called
      # whenever a chunk of data was written out to the kernel
      my $get_chunk_cb = sub {
         my ($data_cb) = @_;

         if ($data_cb) {
            print "get next chunk, $last_pos of $size!\n";
         } else {
            print "sent last chunk, no more required!\n";
         }

         return unless $data_cb; # in case the connection went away...

         my $chunk = '';

         # use IO::AIO again, to async read from disk
         # you decide what chunks you want to send btw.
         # here we send 4096 bytes on each chunk read.
         aio_read $fh, $last_pos, 4096, $chunk, 0, sub {
            if ($_[0] > 0) {
               $last_pos += $_[0];
               print "read $_[0] bytes, sending them...\n";
               $data_cb->($chunk); # when we got another chunk, push it
                                   # over the http connection;
               $chunk = '';

               # and here we just return, and wait for the next call to
               # $get_chunk_cb when the data is in the kernel.

            } else {
               $data_cb->(); # stop sending data (in case of error or EOF)
               return;
            }
         };
      };

      $req->respond (
         [
            200, 'ok', {
               'Content-Type'   => $mime,
 #              'Content-Length' => $size
            },
            $get_chunk_cb
         ]
      );
   };
}

$httpd->reg_cb (
   '' => sub {
      my ($httpd, $req) = @_;
      $req->respond ({ content => ['text/html', <<'CONT']});
         <html><body><h1>Large Download Example!</h1>
         <a href="/test">download file</a>
         </body></html>
CONT
   },
   '/test' => sub {
      my ($httpd, $req) = @_;
      $httpd->stop_request;

      print "sending file ...\n";
      send_file ($req);
   },
);

$cvar->wait;