App-MHFS
view release on metacpan or search on metacpan
lib/MHFS/HTTP/Server/Client/Request.pm view on Meta::CPAN
$msg = "307 Temporary Redirect";
}
$msg .= "\r\n<a href=\"$url\"></a>\r\n";
$self->SendHTML($msg, {'code' => $code});
}
# encodes path and querystring
# path and query string keys and values must be bytes not unicode string
sub SendRedirect {
my ($self, $code, $path, $qs) = @_;
my $url;
# encode the path component
while(length($path)) {
my $slash = index($path, '/');
my $len = ($slash != -1) ? $slash : length($path);
my $pathcomponent = substr($path, 0, $len, '');
$url .= uri_escape($pathcomponent);
if($slash != -1) {
substr($path, 0, 1, '');
$url .= '/';
}
}
# encode the querystring
if($qs) {
$url .= '?';
foreach my $key (keys %{$qs}) {
my @values;
if(ref($qs->{$key}) ne 'ARRAY') {
push @values, $qs->{$key};
}
else {
@values = @{$qs->{$key}};
}
foreach my $value (@values) {
$url .= uri_escape($key).'='.uri_escape($value) . '&';
}
}
chop $url;
}
@_ = ($self, $code, $url);
goto &SendRedirectRawURL;
}
sub SendLocalFile {
my ($self, $requestfile) = @_;
my $start = $self->{'header'}{'_RangeStart'};
my $client = $self->{'client'};
# open the file and get the size
my %fileitem = ('requestfile' => $requestfile);
my $currentsize;
if($self->{'method'} ne 'HEAD') {
my $FH;
if(! open($FH, "<", $requestfile)) {
say "SLF: open failed";
$self->Send404;
return;
}
binmode($FH);
my $st = stat($FH);
if(! $st) {
$self->Send404();
return;
}
$currentsize = $st->size;
$fileitem{'fh'} = $FH;
}
else {
$currentsize = (-s $requestfile);
}
# seek if a start is specified
if(defined $start) {
if($start >= $currentsize) {
$self->Send416($currentsize);
return;
}
elsif($fileitem{'fh'}) {
seek($fileitem{'fh'}, $start, 0);
}
}
# get the maximumly possible file size. 99999999999 signfies unknown
my $get_current_size = sub {
return $currentsize;
};
my $done;
my $ts;
my $get_max_size = sub {
if($done) {
return $ts;
}
my $locksz = LOCK_GET_LOCKDATA($requestfile);
if(defined($locksz)) {
$ts = ($locksz || 0);
}
else {
$done = 1;
$ts = ($get_current_size->() || 0);
}
};
my $filelength = $get_max_size->();
# truncate to the [potentially] satisfiable end
if(defined $self->{'header'}{'_RangeEnd'}) {
$self->{'header'}{'_RangeEnd'} = min($filelength-1, $self->{'header'}{'_RangeEnd'});
}
# setup callback for retrieving current file size if we are following the file
if($fileitem{'fh'}) {
if(! $done) {
$get_current_size = sub {
return stat($fileitem{'fh'})
};
}
my $get_read_filesize = sub {
my $maxsize = $get_max_size->();
if(defined $self->{'header'}{'_RangeEnd'}) {
my $rangesize = $self->{'header'}{'_RangeEnd'}+1;
return $rangesize if($rangesize <= $maxsize);
}
return $maxsize;
};
$fileitem{'get_current_length'} = $get_read_filesize;
}
# flag to add SharedArrayBuffer headers
my @SABwhitelist = ('static/music_worklet_inprogress/index.html');
my $allowSAB;
foreach my $allowed (@SABwhitelist) {
if(index($requestfile, $allowed, length($requestfile)-length($allowed)) != -1) {
$allowSAB = 1;
last;
}
}
# finally build headers and send
if($filelength == 99999999999) {
$filelength = undef;
}
my $mime = getMIME($requestfile);
my $opt = {
'size' => $filelength,
'mime' => $mime,
'allowSAB' => $allowSAB
};
if($self->{'responseopt'}{'cd_file'}) {
$opt->{$self->{'responseopt'}{'cd_file'}} = basename($requestfile);
}
$self->_SendDataItem(\%fileitem, $opt);
}
# currently only supports fixed filelength
sub SendPipe {
my ($self, $FH, $filename, $filelength, $mime) = @_;
if(! defined $filelength) {
$self->Send404();
}
$mime //= getMIME($filename);
binmode($FH);
my %fileitem;
$fileitem{'fh'} = $FH;
$fileitem{'get_current_length'} = sub {
my $tocheck = defined $self->{'header'}{'_RangeEnd'} ? $self->{'header'}{'_RangeEnd'}+1 : $filelength;
return min($filelength, $tocheck);
};
$self->_SendDataItem(\%fileitem, {
'size' => $filelength,
( run in 0.901 second using v1.01-cache-2.11-cpan-39bf76dae61 )