You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl@perl.apache.org by Thomas Lindgren <th...@diino.net> on 2008/11/24 17:18:58 UTC

How to reject requests before request body is sent?

Hi all,

I'm using mod_perl2. I'd like to reject user requests, e.g., very large
PUTs, after examining headers and authorizing the user, but before the
request body is read. Quota checking could be an example of where this is
useful.

However, at this time, even if I return an error in the handler, it
(surprisingly) seems as if the request body still is uploaded. What to do?

Here is a boiled-down config, which just returns an error code after reading
the header. In the real code, I also examine the headers a bit before
deciding, but here I'm just interested in the case when the request is
rejected. The example below uses the HeaderParser hook, but the same things
seems to happen with a Fixup handler.

...
<Location /test>
   PerlHeaderParserHandler Test::Reject
</Location>

The handler itself just returns an error code:

...
sub handler {
  my  $r = shift;
  return Apache2::Const::HTTP_INSUFFICIENT_STORAGE;
}

Running a big PUT to $SERVER with curl transfers the body anyway (but then
returns the error):

# curl -o put.txt --basic --user a:b -T example.vmdk 'http://
$SERVER/test/foo.vmdk'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time
Current
                                 Dload  Upload   Total   Spent    Left
Speed
  4 2743M    0     0    4  123M      0  9185k  0:05:05  0:00:13  0:04:52
10.4M^C

The only way to trigger an early close so far has been to die in the
handler, which confuses clients and so on.

The server could as a worst case alternative actually close the socket, but
that feels inelegant and hackish. So, my question to the esteemed list, how
should this sort of thing best be done? Have I forgotten something basic?
Should I return something else? Is there a more appropriate phase to do
this? Should I do it another way entirely?

Best,
Thomas

Re: How to reject requests before request body is sent?

Posted by Fred Moyer <fr...@redhotpenguin.com>.
On Mon, Nov 24, 2008 at 8:18 AM, Thomas Lindgren
<th...@diino.net> wrote:
> Hi all,
>
> I'm using mod_perl2. I'd like to reject user requests, e.g., very large
> PUTs, after examining headers and authorizing the user, but before the
> request body is read. Quota checking could be an example of where this is
> useful.
>
> However, at this time, even if I return an error in the handler, it
> (surprisingly) seems as if the request body still is uploaded. What to do?

I don't think that partial uploads are supported in the HTTP spec.
I'd suggest an inputfilter like Adam said, and maybe close the
connection if the request isn't what you want.  A bit of a hack like
you said, but it should work if your client is aware of it.

>
> Here is a boiled-down config, which just returns an error code after reading
> the header. In the real code, I also examine the headers a bit before
> deciding, but here I'm just interested in the case when the request is
> rejected. The example below uses the HeaderParser hook, but the same things
> seems to happen with a Fixup handler.
>
> ...
> <Location /test>
>    PerlHeaderParserHandler Test::Reject
> </Location>
>
> The handler itself just returns an error code:
>
> ...
> sub handler {
>   my  $r = shift;
>   return Apache2::Const::HTTP_INSUFFICIENT_STORAGE;
> }
>
> Running a big PUT to $SERVER with curl transfers the body anyway (but then
> returns the error):
>
> # curl -o put.txt --basic --user a:b -T example.vmdk
> 'http://$SERVER/test/foo.vmdk'
>   % Total    % Received % Xferd  Average Speed   Time    Time     Time
> Current
>                                  Dload  Upload   Total   Spent    Left
> Speed
>   4 2743M    0     0    4  123M      0  9185k  0:05:05  0:00:13  0:04:52
> 10.4M^C
>
> The only way to trigger an early close so far has been to die in the
> handler, which confuses clients and so on.
>
> The server could as a worst case alternative actually close the socket, but
> that feels inelegant and hackish. So, my question to the esteemed list, how
> should this sort of thing best be done? Have I forgotten something basic?
> Should I return something else? Is there a more appropriate phase to do
> this? Should I do it another way entirely?
>
> Best,
> Thomas
>
>

Re: How to reject requests before request body is sent?

Posted by Thomas Lindgren <th...@diino.net>.
On Mon, Nov 24, 2008 at 9:55 PM, Adam Prime <ad...@utoronto.ca> wrote:

> This could be useful, but I think it's also pretty much impossible.  From
> what I understand, the entire request is read before any processing is done
> at all, and definitely before the HeaderParserPhase is executed, which is
> why you're seeing the behavior you describe.
>

Actually, I see log entries (not shown in the example) long before the big
example upload finishes, so the handlers appear to run before the request
completes. Furthermore, one description of RUN_ALL sort of hints that errors
should abort the cycle ("Mod_perl 2 users guide", p. 65), but, except if the
handler dies, it looks as if such errors are held back until the request has
been fully received. Too bad.

Thanks for the help guys, I'll see whether an input filter helps. Or perhaps
that socket hack.

Best,
Thomas

Re: How to reject requests before request body is sent?

Posted by Adam Prime <ad...@utoronto.ca>.
Thomas Lindgren wrote:
> Hi all,
>
> I'm using mod_perl2. I'd like to reject user requests, e.g., very 
> large PUTs, after examining headers and authorizing the user, but 
> before the request body is read. Quota checking could be an example of 
> where this is useful.
>
> However, at this time, even if I return an error in the handler, it 
> (surprisingly) seems as if the request body still is uploaded. What to do?
> <snip>
>
> The only way to trigger an early close so far has been to die in the 
> handler, which confuses clients and so on.
>
> The server could as a worst case alternative actually close the 
> socket, but that feels inelegant and hackish. So, my question to the 
> esteemed list, how should this sort of thing best be done? Have I 
> forgotten something basic? Should I return something else? Is there a 
> more appropriate phase to do this? Should I do it another way entirely?
This could be useful, but I think it's also pretty much impossible.  
 From what I understand, the entire request is read before any 
processing is done at all, and definitely before the HeaderParserPhase 
is executed, which is why you're seeing the behavior you describe.

The only other technique you might try would be an InputFilter, but I 
have a feeling that even that wouldn't really stop the upload from 
happening (ie the consumption of bandwidth).  I think this has more to 
do with TCP pipelining than it does with anything else, so it's actually 
not "fixable" in the application at all.

Adam