libwww-perl / libwww-perl/HTTP-Daemon

Setting $\ to "\n" inserts newlines in the file send with $c->send_file() or $c->send_file_response()

Open
#48 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Perl
Stars
6
Forks
17
PR merge metrics
No merged PRs in 30d

Description

When you set $\ ($OUTPUT_RECORD_SEPARATOR) to anything other than "" (empty string) in the server script,
the value of $\ is inserted multiple times in a file send with $c->send_file() or $c->send_file_response();

It may not be too bad for a text file but it makes a BINARY FILE corrupted and useless, a video for example.

I put an example of the server and client script that I used.

I also found the problem.

This is coming from the send_file() method.
This method reads the file to be send by chunk of 8K and it prints the temporary buffer to a filehandle.

And because $\ is global, a new line is inserted on each print of HTTP::Daemon::send_file().

The SOLUTION is to put :
local ($\ = "");
in the method send_file()

The reason I didn't make a pull request is because I am not sure if that is the best solution.

Would it be better to put local ($\ = ""); at the top of the package for example ?

ALSO,
the same problem that I found might also impact other methods of this package
because there is other methods that prints to a filehandle. And I do not know enough HTTP to decide myself.

In particular, when it concerns the CRLF "\r\n"

Those are the methods that can be possibly impacted : (because of a print to a filehandle)

I put aside methods that print to STDERR.

sub send_status_line {
sub send_crlf {
sub send_basic_header {
sub send_header {
sub send_response {
sub send_redirect {
sub send_error {
sub send_file_response {
sub send_file {

####################################################

EXAMPLE

SERVER SCRIPT

my $file = "/path/to/small/video_file.mp4";
my $port = 3000;
my $d = HTTP::Daemon->new(LocalPort => $port) || die "fail";

$\ = "\n";
print $d->url;

while (my $c = $d->accept) {
        while (my $r = $c->get_request) {
                if ($r->method eq "GET") {
                        print "got a GET request";             # the reason to set $\ to "\n"
                        # $c->send_file_response($file);
                        $c->send_file($file);
                }
        }
        $c->close;
        undef $c;
}

####################################################
CLIENT SCRIPT

my $url = "http://localhost:3000/";
my $req = HTTP::Request->new(GET => $url);
my $ua = LWP::UserAgent->new();
$ua->show_progress(1);
my $res = $ua->request($req);

open FH, ">:bytes", "response.mp4";
print FH $res->content;
close FH;

PS :
Sorry for the indentation, I don't know how that works

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by inspecting HTTP::Daemon's send_file() and send_file_response() entry points, then review the listed methods that print to filehandles. Reproduce the binary transfer with the provided server and client scripts, and verify that the response remains unmodified when $\ is set; done means the affected send paths no longer insert separator data.

Written by the indexing model from the issue text.

Assessment

Tech stack
perl
Domain
networking
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.