Perlbal
view release on metacpan or search on metacpan
lib/Perlbal/ClientHTTPBase.pm view on Meta::CPAN
$res->header("Server", "Perlbal") if $self->{service}{server_tokens};
$res->header("Last-Modified", $lastmod);
$res->header("Content-Type", $mime);
# has to happen after content-length is set to work:
$self->setup_keepalive($res);
return if $self->{service}->run_hook('modify_response_headers', $self);
if ($hd->request_method eq "HEAD" || $not_mod) {
# we can return already, since we know the size
$self->tcp_cork(1);
$self->state('xfer_resp');
$self->write($res->to_string_ref);
$self->write(sub { $self->http_response_sent; });
return;
}
$self->tcp_cork(1); # cork writes to self
$self->write($res->to_string_ref);
$self->state('wait_open');
# gotta send all files, one by one...
my @remain = @$filelist;
$self->{post_sendfile_cb} = sub {
unless (@remain) {
$self->write(sub { $self->http_response_sent; });
return;
}
my $file = shift @remain;
my $fullfile = "$basedir$file";
my $size = $stats->{$file}[7];
Perlbal::AIO::aio_open($fullfile, 0, 0, sub {
my $rp_fh = shift;
# if client's gone, just close filehandle and abort
if ($self->{closed}) {
CORE::close($rp_fh) if $rp_fh;
return;
}
# handle errors
if (! $rp_fh) {
# couldn't open the file we had already successfully stat'ed.
# FIXME: do 500 vs. 404 vs whatever based on $!
return $self->close('aio_open_failure');
}
$self->{reproxy_file} = $file;
$self->reproxy_fh($rp_fh, $size);
});
};
$self->{post_sendfile_cb}->();
}
sub check_req_headers {
my Perlbal::ClientHTTPBase $self = shift;
my Perlbal::HTTPHeaders $hds = $self->{req_headers};
if ($self->{service}->trusted_ip($self->peer_ip_string)) {
my @ips = split /,\s*/, ($hds->header("X-Forwarded-For") || '');
# This list may be empty, and that's OK, in that case we should unset the
# observed_ip_string, so no matter what we'll use the 0th element, whether
# it happens to be an ip string, or undef.
$self->observed_ip_string($ips[0]);
}
return;
}
sub try_index_files {
my Perlbal::ClientHTTPBase $self = shift;
my ($hd, $res, $uri, $filepos) = @_;
# make sure this starts at 0 initially, and fail if it's past the end
$filepos ||= 0;
if ($filepos >= scalar(@{$self->{service}->{index_files} || []})) {
unless ($self->{service}->{dirindexing}) {
# just inform them that listing is disabled
$self->_simple_response(200, "Directory listing disabled");
return;
}
# ensure uri has one and only one trailing slash for better URLs
$uri =~ s!/*$!/!;
# open the directory and create an index
my $body = "<html><body>";
my $file = $self->{service}->{docroot} . $uri;
$res->header("Content-Type", "text/html");
opendir(D, $file);
foreach my $de (sort readdir(D)) {
if (-d "$file/$de") {
$body .= "<b><a href='$uri$de/'>$de</a></b><br />\n";
} else {
$body .= "<a href='$uri$de'>$de</a><br />\n";
}
}
closedir(D);
$body .= "</body></html>";
$res->header("Content-Length", length($body));
$self->setup_keepalive($res);
$self->state('xfer_resp');
$self->tcp_cork(1); # cork writes to self
$self->write($res->to_string_ref);
$self->write(\$body);
$self->write(sub { $self->http_response_sent; });
return;
}
# construct the file path we need to check
my $file = $self->{service}->{index_files}->[$filepos];
my $fullpath = $self->{service}->{docroot} . $uri . '/' . $file;
# now see if it exists
Perlbal::AIO::aio_stat($fullpath, sub {
return if $self->{closed};
( run in 1.771 second using v1.01-cache-2.11-cpan-39bf76dae61 )