develooper Front page | perl.libwww | Postings from December 2000

HTTP::Daemon to stream content chain by chain

From:
Mike Blazer
Date:
December 5, 2000 08:58
Subject:
HTTP::Daemon to stream content chain by chain
Message ID:
3A2D14F9.AD55D00F@mail.nevalink.ru
Hello guys,
I was writing an HTTP proxy recently and I was looking for some way not to wait until the whole response is here - but to stream the received chunks immediatelly. Seems like HTTP::Daemon::send_response does not give this ability, it's waiting for a fully qualified HTTP::Response object as an argument.

I wanted to have two functions: 1 - to send headers to client as soon as my proxy received them; 2- to send the content chunks to avoid delays on the client-side.

So, I wrote a quich hack:

package HTTP::Daemon::ClientConn;
use strict;

use HTTP::Status;

my $CRLF = "\015\012";   # "\r\n" is not portable

# ref $content = "CODE" cases removed (HTTP/1.1)
sub send_response_headers
{
    my $self  = shift;
    my $res   = shift;

    if (!ref $res) {
	$res ||= RC_OK;
	require HTTP::Response;
	$res = HTTP::Response->new($res, @_);
    }

    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");
	} elsif ($res->request && $res->request->method eq "HEAD") {
	    # probably OK
	} else {
	    $self->force_last_request;
	}

	print $self $res->headers_as_string($CRLF);
	print $self $CRLF;  # separates headers and content
    }
}

sub send_response_chunk
{
    my $self  = shift;
    my $res   = shift;
    my $chunk = shift;

    unless ($self->antique_client) {
	my $code = $res->code;
	if ($code =~ /^(1\d\d|[23]04)$/) {
	    # make sure content is empty
	    $res->remove_header("Content-Length");
	    $chunk = "";
        }
    }
    print $self $chunk;
}

1;
======= end of code ========

This is in fact nothing more then some parts of the send_response() function in some other order.

But unfortunatelly I'm unfamiliar with the (ref($content) eq "CODE") case, so I've just removed that part of the code - anyways the proxy now supports HTTP/1.0 only as it is LWP-based.

Gisle, please, if you'll find this useful - may be you'll update HTTP::Daemon with something like this.

To those who are interested - I used these two functions in the subroutine passed as a second argument (callback) to $ua->request. In fact this code-ref is used in LWP::Protocol::collect() to do something after the content-chunk was parsed (but not added to content yet).
After that my proxy sarted doing something more-or-less real.

May be I'm missing something? May be the current HTTP::Daemon already provides this "streaming" features?

Regards
-- 
==================================
Mike Blazer
blazer@mail.nevalink.ru
http://base.dux.ru/guest/fno/perl/
==================================



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About