Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/HTTP/Request.pm
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ sub as_string
my $proto = $self->protocol;
$req_line .= " $proto" if $proto;

return join($eol, $req_line, $self->SUPER::as_string(@_));
return join($eol, $req_line, $self->SUPER::as_string($eol));
}

sub dump
Expand Down
2 changes: 1 addition & 1 deletion lib/HTTP/Response.pm
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ sub as_string
my $proto = $self->protocol;
$status_line = "$proto $status_line" if $proto;

return join($eol, $status_line, $self->SUPER::as_string(@_));
return join($eol, $status_line, $self->SUPER::as_string($eol));
}


Expand Down
108 changes: 108 additions & 0 deletions t/request-as-string-parse.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
#!/usr/bin/perl
# Test that as_string and parse are commutative for HTTP::Request (issue #62959)

use strict;
use warnings;

use Test::More tests => 9;

use HTTP::Request;

# Test 1: Request with content (no trailing newline)
{
my $r = HTTP::Request->new(POST => 'http://example.com/');
$r->content("This is request content");
my $original_content = $r->content;

my $s = $r->as_string;
my $t = HTTP::Request->parse($s);

is($t->content, $original_content,
'Content without trailing newline preserved through as_string/parse');
}

# Test 2: Request with content ending in newline
{
my $r = HTTP::Request->new(POST => 'http://example.com/');
$r->content("Content with newline\n");
my $original_content = $r->content;

my $s = $r->as_string;
my $t = HTTP::Request->parse($s);

is($t->content, $original_content,
'Content with trailing newline preserved through as_string/parse');
}

# Test 3: Request with multiline content
{
my $r = HTTP::Request->new(POST => 'http://example.com/');
$r->content("Line 1\nLine 2\nLine 3");
my $original_content = $r->content;

my $s = $r->as_string;
my $t = HTTP::Request->parse($s);

is($t->content, $original_content,
'Multiline content without trailing newline preserved');
}

# Test 4: Request with empty content
{
my $r = HTTP::Request->new(GET => 'http://example.com/');
$r->content("");
my $original_content = $r->content;

my $s = $r->as_string;
my $t = HTTP::Request->parse($s);

is($t->content, $original_content,
'Empty content preserved through as_string/parse');
}

# Test 5: Request with method and URI
{
my $r = HTTP::Request->new(POST => 'http://example.com/path');
$r->content("Test content");
my $original_content = $r->content;
my $original_uri = $r->uri->as_string;

my $s = $r->as_string;
my $t = HTTP::Request->parse($s);

is($t->content, $original_content,
'Content preserved with method and URI');
is($t->uri->as_string, $original_uri, 'URI preserved');
is($t->method, 'POST', 'Method preserved');
}

# Test 6: Request with explicit \r\n line endings
{
my $r = HTTP::Request->new(GET => 'http://example.com/');
$r->content("Test content");
my $original_content = $r->content;

my $s = $r->as_string("\r\n");
my $t = HTTP::Request->parse($s);

is($t->content, $original_content,
'Content preserved with explicit CRLF line endings');
}

# Test 7: Multiple round trips
{
my $r = HTTP::Request->new(POST => 'http://example.com/');
$r->content("Round trip test");
my $original_content = $r->content;

# First round trip
my $s1 = $r->as_string;
my $t1 = HTTP::Request->parse($s1);

# Second round trip
my $s2 = $t1->as_string;
my $t2 = HTTP::Request->parse($s2);

is($t2->content, $original_content,
'Content preserved through multiple round trips');
}
107 changes: 107 additions & 0 deletions t/response-as-string-parse.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/usr/bin/perl
# Test that as_string and parse are commutative (issue #62959)

use strict;
use warnings;

use Test::More tests => 9;

use HTTP::Response;

# Test 1: Response with content (no trailing newline)
{
my $r = HTTP::Response->new;
$r->content("This is a sample of content");
my $original_content = $r->content;

my $s = $r->as_string;
my $t = HTTP::Response->parse($s);

is($t->content, $original_content,
'Content without trailing newline preserved through as_string/parse');
}

# Test 2: Response with content ending in newline
{
my $r = HTTP::Response->new;
$r->content("Content with newline\n");
my $original_content = $r->content;

my $s = $r->as_string;
my $t = HTTP::Response->parse($s);

is($t->content, $original_content,
'Content with trailing newline preserved through as_string/parse');
}

# Test 3: Response with multiline content
{
my $r = HTTP::Response->new;
$r->content("Line 1\nLine 2\nLine 3");
my $original_content = $r->content;

my $s = $r->as_string;
my $t = HTTP::Response->parse($s);

is($t->content, $original_content,
'Multiline content without trailing newline preserved');
}

# Test 4: Response with empty content
{
my $r = HTTP::Response->new;
$r->content("");
my $original_content = $r->content;

my $s = $r->as_string;
my $t = HTTP::Response->parse($s);

is($t->content, $original_content,
'Empty content preserved through as_string/parse');
}

# Test 5: Response with code and message
{
my $r = HTTP::Response->new(200, "OK");
$r->content("Test content");
my $original_content = $r->content;

my $s = $r->as_string;
my $t = HTTP::Response->parse($s);

is($t->content, $original_content,
'Content preserved with status code and message');
is($t->code, 200, 'Status code preserved');
is($t->message, 'OK', 'Status message preserved');
}

# Test 6: Response with explicit \r\n line endings
{
my $r = HTTP::Response->new(200, "OK");
$r->content("Test content");
my $original_content = $r->content;

my $s = $r->as_string("\r\n");
my $t = HTTP::Response->parse($s);

is($t->content, $original_content,
'Content preserved with explicit CRLF line endings');
}

# Test 7: Multiple round trips
{
my $r = HTTP::Response->new(200, "OK");
$r->content("Round trip test");
my $original_content = $r->content;

# First round trip
my $s1 = $r->as_string;
my $t1 = HTTP::Response->parse($s1);

# Second round trip
my $s2 = $t1->as_string;
my $t2 = HTTP::Response->parse($s2);

is($t2->content, $original_content,
'Content preserved through multiple round trips');
}
Loading