Description
request_type_with_data (used by POST, PUT, PATCH, and OPTIONS) unconditionally sets a Content-Type header to application/x-www-form-urlencoded even when no body content is supplied.
In lib/HTTP/Request/Common.pm:
sub request_type_with_data {
my $type = shift;
my $url = shift;
my $req = HTTP::Request->new($type => $url);
my $content;
$content = shift if @_ and ref $_[0];
my($k, $v);
while (($k,$v) = splice(@_, 0, 2)) {
if (lc($k) eq 'content') {
$content = $v;
}
else {
$req->push_header($k, $v);
}
}
my $ct = $req->header('Content-Type');
unless ($ct) {
$ct = 'application/x-www-form-urlencoded'; # default
}
elsif ($ct eq 'form-data') {
$ct = 'multipart/form-data';
}
# ... content encoding ...
$req->header('Content-Type' => $ct); # always set
if (defined($content)) {
$req->header('Content-Length' =>
length($content)) unless ref($content);
$req->content($content);
}
else {
$req->header('Content-Length' => 0);
}
$req;
}
Content-Type is resolved before checking whether $content is defined, and the assignment at the end is unconditional.
Impact
For HTTP methods that commonly have no body (e.g. OPTIONS without a body), a caller doing:
use HTTP::Request::Common;
my $req = OPTIONS 'http://example.com';
receives a request with:
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
Neither header is meaningful for a bodyless OPTIONS request.
Suggested fix
Move the Content-Type assignment inside the if (defined($content)) block so it only applies when there is actual content to describe:
if (defined($content)) {
$req->header('Content-Type' => $ct);
$req->header('Content-Length' =>
length($content)) unless ref($content);
$req->content($content);
}
else {
$req->header('Content-Length' => 0);
}
This would make request_type_with_data consistent with _simple_req (used by GET, HEAD, DELETE), which does not set Content-Type at all.
Description
request_type_with_data(used by POST, PUT, PATCH, and OPTIONS) unconditionally sets aContent-Typeheader toapplication/x-www-form-urlencodedeven when no body content is supplied.In
lib/HTTP/Request/Common.pm:Content-Type is resolved before checking whether
$contentis defined, and the assignment at the end is unconditional.Impact
For HTTP methods that commonly have no body (e.g. OPTIONS without a body), a caller doing:
receives a request with:
Content-Type: application/x-www-form-urlencodedContent-Length: 0Neither header is meaningful for a bodyless OPTIONS request.
Suggested fix
Move the Content-Type assignment inside the
if (defined($content))block so it only applies when there is actual content to describe:This would make
request_type_with_dataconsistent with_simple_req(used by GET, HEAD, DELETE), which does not set Content-Type at all.