[Dancer-users] dancer2's prototype is there, feedback needed

Assaf Gordon gordon at cshl.edu
Wed Oct 12 19:48:57 CEST 2011


Hello Alexis,

I'm still getting this behavior (POST with parameters is stuck) with the latest dancer2.
But I have more details.

Alexis Sukrieh wrote, On 10/08/11 05:54:
> 2011/10/3 Assaf Gordon <gordon at cshl.edu>:
>> ## Access the app with "POST" (and parameters) - FAILS - the request hangs, BEFORE even reaching my 'post' handler code.
>> $ curl -X POST -d name=foobar http://localhost:3000/
>> [ XXXX - Stuck - XXXX ]
> 
> I can't reproduce that. Here is what I did:
> 
> $ curl -I -X POST http://0:3000/
> HTTP/1.0 200 OK

The missing part is adding POST parameters, with the following command:

$ curl -I -X POST -d "hello=world" http://0:3000/


Here's what happens in my setup, to the best of my ability to debug dancer2:

1. Request arrives (after some trials and tribulations) to "Dancer::Core::Dispatcher->dispatch()"  which finds the appropriate route.

2. "Dispatch()" runs:
       my $http_method = lc $context->request->method;

but $context->request DOES NOT exist, so the "moo" auto-builder thingy calls "Dancer::Core::Context::_build_request".


3. A new Dancer::Core::Request object is created, goes to "Dancer::Core::Request->BUILD".
  Eventually calls "$self->_build_params()".


4. "Dancer::Core::Request->_build_params()" calls "_parse_post_params()"

5. "Dancer::Core::Request->_parse_post_params()" calls "_read_to_end()" 

6. "Dancer::Core::Request->_read_to_end()" looks like this:
================
 sub _read_to_end {
     my ($self) = @_;
 
     my $content_length = $self->content_length;
     return unless $self->_has_something_to_read();
 
     if ($content_length > 0) {
         while (my $buffer = $self->_read()) {
             $self->{body} .= $buffer;
             $self->{_http_body}->add($buffer);
         }
     }
 
     return $self->{body};
 }
===============

I assume in your testing (without POST parameters), "content_length" was zero, and so nothing is read, and the function returns undef.

In my case, "content_length" is the length of the POST parameters (e.g. "hello=world" = 11 characters).

So it calls "$self->_read()".

7. "read_()" looks like this (without my sprinkled "warn" statements):
===================
sub _read {
    my ($self,)   = @_;
    my $remaining = $self->content_length - $self->{_read_position};
    warn "#### remaining = $remaining";
    my $maxlength = $self->{_chunk_size};
    warn "#### maxlength = $maxlength";

    return if ($remaining <= 0);

    my $readlen = ($remaining > $maxlength) ? $maxlength : $remaining;
    warn "#### readlen = $readlen";
    my $buffer;
    my $rc;

    warn "##### before read";
    warn "###### input_handle = " . dump($self->input_handle) ;
    $rc = $self->input_handle->read($buffer, $readlen);
    warn "##### after read";

    if (defined $rc) {
        $self->{_read_position} += $rc;
        return $buffer;
    }
    else {
        croak "Unknown error reading input: $!";
    }
}
===================

And Dancer2 is stuck in the:
      $rc = $self->input_handle->read($buffer, $readlen);
Statement, unable to read the expected number of characters.

The printed output is:
========
#### remaining = 11 at /home/gordon/sources/dancer2/lib/Dancer/Core/Request.pm line 552, <DATA> line 16.
#### maxlength = 4096 at /home/gordon/sources/dancer2/lib/Dancer/Core/Request.pm line 554, <DATA> line 16.
#### readlen = 11 at /home/gordon/sources/dancer2/lib/Dancer/Core/Request.pm line 559, <DATA> line 16.
##### before read at /home/gordon/sources/dancer2/lib/Dancer/Core/Request.pm line 563, <DATA> line 16.
###### input_handle = do {
  require Symbol;
  bless(Symbol::gensym(), "FileHandle");
} at /home/gordon/sources/dancer2/lib/Dancer/Core/Request.pm line 564, <DATA> line 16.
========

Because the "read" function never returns.

Not sure if this is a problem in my setup or in dancer2, but it's reproducible every time.


regards,
 -assaf.




More information about the Dancer-users mailing list