$status ||= RC_OK;
$message ||= status_message($status) || "";
$proto ||= $HTTP::Daemon::PROTO || "HTTP/1.1";
print $self "$proto $status $message$CRLF";
}
sub send_crlf
{
my $self = shift;
print $self $CRLF;
}
sub send_basic_header
{
my $self = shift;
return if $self->antique_client;
$self->send_status_line(@_);
print $self "Date: ", time2str(time), $CRLF;
my $product = $self->daemon->product_tokens;
print $self "Server: $product$CRLF" if $product;
}
sub send_header
{
my $self = shift;
while (@_) {
my($k, $v) = splice(@_, 0, 2);
$v = "" unless defined($v);
print $self "$k: $v$CRLF";
}
}
sub send_response
{
my $self = shift;
my $res = shift;
if (!ref $res) {
$res ||= RC_OK;
$res = HTTP::Response->new($res, @_);
}
my $content = $res->content;
my $chunked;
unless ($self->antique_client) {
my $code = $res->code;
$self->send_basic_header($code, $res->message, $res->protocol);
if ($code =~ /^(1\d\d|[23]04)$/) {
# make sure content is empty
$res->remove_header("Content-Length");
$content = "";
}
elsif ($res->request && $res->request->method eq "HEAD") {
# probably OK
}
elsif (ref($content) eq "CODE") {
if ($self->proto_ge("HTTP/1.1")) {
$res->push_header("Transfer-Encoding" => "chunked");
$chunked++;
}
else {
$self->force_last_request;
}
}
elsif (length($content)) {
$res->header("Content-Length" => length($content));
}
else {
$self->force_last_request;
$res->header('connection','close');
}
print $self $res->headers_as_string($CRLF);
print $self $CRLF; # separates headers and content
}
if ($self->head_request) {
# no content
}
elsif (ref($content) eq "CODE") {
while (1) {
my $chunk = &$content();
last unless defined($chunk) && length($chunk);
if ($chunked) {
printf $self "%x%s%s%s", length($chunk), $CRLF, $chunk, $CRLF;
}
else {
print $self $chunk;
}
}
print $self "0$CRLF$CRLF" if $chunked; # no trailers either
}
elsif (length $content) {
print $self $content;
}
}
sub send_redirect
{
=5= |