On Saturday December 13, 2003 06:27, A. Pagaltzis wrote:
> * David Robins <[EMAIL PROTECTED]> [2003-12-13 12:08]:
> > I'd like to contribute an HTTP::Parser module to CPAN.
...
> > "parse" which takes some text and either:
> > dies (on error) (I can return a string if people prefer it), or returns:
> > 0: want more data but don't know how much
> > -1: like 0 but a hint that we want a line
> > <n>: want n bytes more
> > HTTP::Request object: finished parsing the request.
>
> You're trying to make a single value do duble duty, and that
> doesn't work too well. The following code is the best I could
> come up with using your interface - note this is after I've
...
>   my ($req, $ret);
>   my $data = get_data(-1);
>
>   until(ref($req = $ret = $httpp->parse($data))) {
>     if(not $ret) {
>       # 0, need more data, no idea how much
>       $data = get_data(-1);
>     }
>     elsif(-1 == $ret) {
>       $data = get_data(-1);
>       # [ split off one line, feed it in ]
>     }
>     else {
>       # $ret bytes (probably the request body, right?)
>       $data = get_data($bytes);
>     }
>   }

Thanks for taking the time to suggest changes, and I probably will change the 
return value to make it more "perlish" etc.  A note about the above: a hint 
that it wants X bytes or a complete line is just that, a hint, and it's 
perfectly fine to not send a full line (you'll just get back the same 
"want-line" hint) or to send more than a full line; similarly you don't have 
to send exactly X bytes when "requested" to.

I've also thought of another condition that isn't detected, though: if you 
send too much data (more than is required for a request), parse() won't tell 
you how much you went over.

...
> Code using this interface would read something like this:
>
>   my $data = get_data(-1);
>
>   while(my $bytes = $httpp->parse($data)) {

I like the ability to do that which you wouldn't be able to with a list; 
perhaps get_request can also return the number of extra bytes (if called in 
list context).

>     $data = $bytes > 0 ? get_data($bytes) : get_data(-1);
>
>     if(-2 == $bytes) {
>       # [ split off one line, feed it in ]
>     }
>   }
>
>   my $req = $httpp->get_request;
>
> Note how this loop handles all the same cases the above convolute
> deals with, and differs only in that it's about a hundred times
> clearer to read.

Well, to be fair, the "above convolute" can be reduced to:

my ($data,$ret) = ('');

until(ref($ret = $httpp->parse($data))) {
  $data = $ret > 0 ? get_data($ret) : get_data(-1);
  # handle -1 condition and send only a single line if desired
}

I'll make the following changes:

parse() will return:
0 on completion of request (call request() to get the request, call data() to 
get any extra data)
>0 meaning we want (at least - may want more later if we're using chunked 
encoding) that many bytes
-1 meaning we want an indeterminate amount of bytes
-2 meaning we want (at least) a line of data
parse() will also accept undef as a parameter

data() will return:
the current unparsed data, this only really has relevance after a request is 
completed (maybe also a data_size() method?)

request() will return:
the HTTP::Request object for the last completed request, or undef if none

-- 
Dave
Isa. 40:31

Reply via email to