Mailing List Archive

HTTP headers returned from GET vs HEAD
I've been playing with a toy application and inspecting its responses to
various HTTP methods and noticed that Content-Length is missing from the
HEAD response. Both Catalyst::Action::RenderView and C::A::Serialize
(from the C::A::REST package) seem to take the easy way out and "return
1 if $c->req->method eq 'HEAD'". Does anyone with CAR history know why
this is?

To provide message-body-based headers (content-length, last-modified,
content-md5, etc) I'm doing this:

sub render : ActionClass('RenderView') { }

sub end : Private {
my $self = shift;
my ($c) = @_;

$c->forward('render');

# see also Catalyst::Action::RenderView or ::Serialize
if ($c->req->method eq 'HEAD') {
my $view = $c->view
|| die sprintf("%s could not find a view to forward to.\n",
__PACKAGE__);
$c->forward($view);
}

# fun with headers, for example...
# or enable P::M::ContentMD5
if ($c->res->has_body) {
my $md5 = Digest::MD5::md5_hex($c->res->body);
$c->res->headers->header(Content-MD5 => $md5);
}
}

I've noted that while $c->res->body now has my rendered view, it gets
removed by Plack::Middleware::Head prior to returning the response, so I
don't have to worry about that detail.

--Trevor

_______________________________________________
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/
Re: HTTP headers returned from GET vs HEAD [ In reply to ]
Content Length auto detection was moved from Catalyst core to middleware in a recent build of Catalyst.  Its likely that the view you are using isn't bothering to set the length and the middleware is failing to provide it properly since the Head middleware has already removed it.

Since the content length SHOULD be provided for the case of HEAD, could you provide a test case and lets see if shuffling the order of the registered middleware fixes this problem?

There's a method called 'registered_middlewares' in Catalyst.pm that dictates the order.  If you can provide me a failing test case in the repo (https://github.com/perl-catalyst/catalyst-runtime) I am sure I could fix it pretty quick.

Sorry for the slow response, BTW, there's also middleware for the md5

Plack::Middleware::ContentMD5 - Automatically sets the Content-MD5 header on all String bodies - metacpan.org


Plack::Middleware::ContentMD5 - Automatically sets the Content-MD5 header on all String bodies...
Automatically sets the Content-MD5 header on all String bodies
View on metacpan.org Preview by Yahoo

I could be talked into adding that as well, although maybe not everyone wants the overhead.

Any thoughts on that?  --jnap
On Wednesday, April 23, 2014 6:50 PM, Trevor Leffler <tleffler@uw.edu> wrote:

I've been playing with a toy application and inspecting its responses to
various HTTP methods and noticed that Content-Length is missing from the
HEAD response.  Both Catalyst::Action::RenderView and C::A::Serialize
(from the C::A::REST package) seem to take the easy way out and "return
1 if $c->req->method eq 'HEAD'".  Does anyone with CAR history know why
this is?

To provide message-body-based headers (content-length, last-modified,
content-md5, etc) I'm doing this:

sub render : ActionClass('RenderView') { }

sub end : Private {
  my $self = shift;
  my ($c) = @_;

  $c->forward('render');

  # see also Catalyst::Action::RenderView or ::Serialize
  if ($c->req->method eq 'HEAD') {
    my $view = $c->view
      || die sprintf("%s could not find a view to forward to.\n",
__PACKAGE__);
    $c->forward($view);
  }

  # fun with headers, for example...
  # or enable P::M::ContentMD5
  if ($c->res->has_body) {
    my $md5 = Digest::MD5::md5_hex($c->res->body);
    $c->res->headers->header(Content-MD5 => $md5);
  }
}

I've noted that while $c->res->body now has my rendered view, it gets
removed by Plack::Middleware::Head prior to returning the response, so I
don't have to worry about that detail.

--Trevor

_______________________________________________
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/
Re: HTTP headers returned from GET vs HEAD [ In reply to ]
Hey,

So when I was looking at this it seemed to me the order of the middleware stack was correct, so I wrote a quick test case:

https://github.com/perl-catalyst/catalyst-runtime/blob/master/t/head_middleware.t


and it does seem to me that this works as desired (if you have an action that provides a body content, but hit it with a HEAD request, then the body gets removed by the Head middleware but not before the ContentLength middleware has time to calculate the missing content length header.  Here's the current middleware stack for the most recent release of Catalyst:

          Plack::Middleware::HTTPExceptions->new,
          Plack::Middleware::RemoveRedundantBody->new,
          Plack::Middleware::FixMissingBodyInRedirect->new,
          Plack::Middleware::ContentLength->new,
          Plack::Middleware::MethodOverride->new,
          Plack::Middleware::Head->new,

Middleware handles a response from the top down (and the request comes the other way, from the bottom up).  In fact I can make my test case fail by reversing the order of the Head and ContentLength middleware, so I am sure this is the case.  I'm adding this test case to the next release of catalyst to help and to help prevent regressions.

jnap
On Thursday, May 1, 2014 6:01 PM, John Napiorkowski <jjn1056@yahoo.com> wrote:

Content Length auto detection was moved from Catalyst core to middleware in a recent build of Catalyst.  Its likely that the view you are using isn't bothering to set the length and the middleware is failing to provide it properly since the Head middleware has already removed it.

Since the content length SHOULD be provided for the case of HEAD, could you provide a test case and lets see if shuffling the order of the registered middleware fixes this problem?

There's a method called 'registered_middlewares' in Catalyst.pm that dictates the order.  If you can provide me a failing test case in the repo (https://github.com/perl-catalyst/catalyst-runtime) I am sure I could fix it pretty quick.

Sorry for the slow response, BTW, there's also middleware for the md5

Plack::Middleware::ContentMD5 - Automatically sets the Content-MD5 header on all String bodies - metacpan.org


Plack::Middleware::ContentMD5 - Automatically sets the Content-MD5 header on all String bodies...
Automatically sets the Content-MD5 header on all String bodies
View on metacpan.org Preview by Yahoo

I could be talked into adding that as well, although maybe not everyone wants the overhead.

Any thoughts on that?  --jnap
On Wednesday, April 23, 2014 6:50 PM, Trevor Leffler <tleffler@uw.edu> wrote:

I've been playing with a toy application and inspecting its responses to
various HTTP methods and noticed that Content-Length is missing from the
HEAD response.  Both Catalyst::Action::RenderView and C::A::Serialize
(from the C::A::REST package) seem to take the easy way out and "return
1 if $c->req->method eq 'HEAD'".  Does anyone with CAR history know why
this is?

To provide message-body-based headers (content-length, last-modified,
content-md5, etc) I'm doing this:

sub render : ActionClass('RenderView') { }

sub end : Private {
  my $self = shift;
  my ($c) = @_;

  $c->forward('render');

  # see also Catalyst::Action::RenderView or ::Serialize
  if ($c->req->method eq 'HEAD') {
    my $view = $c->view
      || die sprintf("%s could not find a view to forward to.\n",
__PACKAGE__);
    $c->forward($view);
  }

  #
fun with headers, for example...
  # or enable P::M::ContentMD5
  if ($c->res->has_body) {
    my $md5 = Digest::MD5::md5_hex($c->res->body);
    $c->res->headers->header(Content-MD5 => $md5);
  }
}

I've noted that while $c->res->body now has my rendered view, it gets
removed by Plack::Middleware::Head prior to returning the response, so I
don't have to worry about that detail.

--Trevor

_______________________________________________
List: Catalyst@lists.scsys.co.uk
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
Dev site: http://dev.catalyst.perl.org/