Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Do not send a chunked body for HEAD requests #87

Merged
merged 1 commit into from

2 participants

therigu Tatsuhiko Miyagawa
therigu

The HTTP 1.1 spec states

The HEAD method is identical to GET except that the server MUST NOT return a message-body in the response

If a Plack app does not set a body or a Content-Length for a response to a HEAD request (which I believe is correct), Starman currently enables chunked encoding and sends the chunked 'footer' in the body of the response. I believe this contradicts the spec (as above) and causes problems with my (nodejs) client.

Server.pm already disables chunked responses for status codes without a body (204 and 304) - this patch does the same for HEAD requests.

The test fails without the patch to the .pm, it has to use the low level IO::Socket::INET so we get the body before the chunked decoding is applied

Tatsuhiko Miyagawa miyagawa merged commit c27699c into from
therigu therigu deleted the branch
therigu

Ah, I've just realised I committed with the wrong email address. I have updated the branch, would you be willing to pull that instead? I realise that would require a forced update, so if you're not willing I understand.

Tatsuhiko Miyagawa
Owner

Yeah i wouldn't do forced update lightly. Sorry about that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 14, 2013
  1. therigu

    Do not send a chunked body for HEAD requests

    Adam Guthrie authored therigu committed
This page is out of date. Refresh to see the latest.
Showing with 49 additions and 1 deletion.
  1. +1 −1  lib/Starman/Server.pm
  2. +48 −0 t/no_chunked_head.t
2  lib/Starman/Server.pm
View
@@ -473,7 +473,7 @@ sub _finalize_response {
if ( $protocol eq 'HTTP/1.1' ) {
if ( !exists $headers{'content-length'} ) {
- if ( $status !~ /^1\d\d|[23]04$/ ) {
+ if ( $status !~ /^1\d\d|[23]04$/ && $env->{REQUEST_METHOD} ne 'HEAD' ) {
DEBUG && warn "[$$] Using chunked transfer-encoding to send unknown length body\n";
push @headers, 'Transfer-Encoding: chunked';
$chunked = 1;
48 t/no_chunked_head.t
View
@@ -0,0 +1,48 @@
+use strict;
+use Test::TCP;
+use IO::Socket::INET;
+use HTTP::Request;
+use HTTP::Response;
+use Plack::Loader;
+use Test::More;
+
+$ENV{PLACK_SERVER} = 'Starman';
+
+test_tcp(
+ client => sub {
+ my $port = shift;
+
+ my $socket = IO::Socket::INET->new(
+ PeerAddr => 'localhost',
+ PeerPort => $port,
+ Proto => 'tcp'
+ ) or die "Failed to connect to server: $!";
+
+ my $request = HTTP::Request->new(
+ HEAD => '/', [ Host => 'localhost' ]
+ );
+ $request->protocol('HTTP/1.1');
+
+ $socket->send($request->as_string("\r\n"));
+ $socket->shutdown(1);
+
+ my $data;
+ while ($socket->connected) {
+ my $buf;
+ $socket->recv($buf, 1024);
+ $data .= $buf;
+ }
+
+ my $res = HTTP::Response->parse($data);
+
+ is $res->content, '';
+ },
+ server => sub {
+ my $port = shift;
+ my $server = Plack::Loader->auto(port => $port, host => '127.0.0.1');
+
+ $server->run(sub { return [ 200, [], [] ] });
+ }
+);
+
+done_testing;
Something went wrong with that request. Please try again.