Make Perl web server deliver an ogg through HTTP to Chrome for a HTML5 audio element -
i writing perl script acts simple web server serves audio files on html5. have succeeded in getting show page web browser html5 audio element. continues listen socket when browser asks audio file via request; hh.ogg in example , tries respond ogg inside message body. works on port 8888.
#!/usr/bin/perl use strict; use warnings; use io::socket; $port = 8888; $server = new io::socket::inet( proto => 'tcp', localport => $port, listen => somaxconn, reuseaddr => 1) or die "unable create server socket"; # server loop while(my $client = $server->accept()) { $client_info; $faviconrequest = 0; while(<$client>) { last if /^\r\n$/; $faviconrequest = 1 if ($_ =~ m/favicon/is); print "\n$_" if ($_ =~ m/get/is); $client_info .= $_; } if ($faviconrequest == 1) { #ignore favicon requests print "favicon request, ignoring , closing client"; close($client); } incoming($client, $client_info) if ($faviconrequest == 0); } sub incoming { print "\n=== incoming request:\n"; $client = shift; print $client &buildresponse($client, shift); print "closing \$client"; close($client); } sub buildresponse { $client = shift; $client_info = shift; $re1='.*?'; $re2='(hh\\.ogg)'; $re=$re1.$re2; print "client info $client_info"; # send file on socket if it's ogg browser wants. return sendfile($client) if ($client_info =~ m/$re/is); $r = "http/1.0 200 ok\r\ncontent-type: text/html\r\n\r\n <html> <head> <title>hello!</title> </head> <body> hello world. <audio src=\"hh.ogg\" controls=\"controls\" preload=\"none\"></audio> </body> </html>"; return $r; } sub sendfile { print "\n>>>>>>>>>>>>>>>>>>>>>>> sendfile"; $client = shift; open $fh, '<' , 'hh.ogg'; $size = -s $fh; print "\nsize: $size"; print $client "allow: get\015\012"; print $client "accept-ranges: none\015\012"; print $client "content-type: \"audio/ogg\"\015\012"; print $client "content-length: $size\015\012"; print "\nsent headers before sending file"; ############################################ #take filehandle , send on socket. $scalar = {local $/; <$fh>}; $offset = 0; while(1) { print "\nsyswriting socket. offset: $offset"; $offset += syswrite($client, $scalar, $size, $offset); last if ($offset >= $size); } print "finished writing socket."; close $fh; return ""; }
the sendfile subroutine called when request matches regex hh.ogg. send few headers in response before writing ogg socket before closing. code works i'd expect in firefox. when press play script receives firefox asking ogg, send on , firefox plays track.
my problem script crashes in google chrome. chrome's developer tools says cannot retrieve hh.ogg. when visit 127.0.0.1:8888 in browser while script running can download hh.ogg. have noticed chrome make multiple requests hh.ogg whereas firefox makes one. i've read may caching reasons? reason why script crashes.
i have
print $client "accept-ranges: none\015\012";
to try , stop behaviour didn't work.
i'm not sure of headers respond chrome let receive file within 1 http response. when script crashes message printed out perl; otherwise there no other errors. quit somewhere inside while loop syswrite() socket.
use of uninitialized value in addition (+) @ ./test.pl line 91, <$fh> line 1.
which referring line.
$offset += syswrite($client, $scalar, $size, $offset);
i don't know why there uninitialized values.
would have ideas why happening? if @ possible i'd accomplish without requiring additional modules cpan.
use real web server instead working , thorougly debugged instead of messing sockets yourself. web more complicated think. run following app plackup --port=8888
.
use http::status qw(http_ok); use path::class qw(file); use plack::request qw(); use router::resource qw(router resource get); $app = sub { ($env) = @_; $req = plack::request->new($env); $router = router { resource '/' => sub { { return $req->new_response( http_ok, [content_type => 'application/xhtml+xml;charset=utf-8'], [ '… html …' ] # array of strings or 1 big string )->finalize; }; }; resource '/hh.ogg' => sub { { return $req->new_response( http_ok, [content_type => 'audio/vorbis'], file(qw(path hh.ogg))->resolve->openr # file handle )->finalize; }; }; }; $router->dispatch($env); };
Comments
Post a Comment