Any way to reset r->request_body to avoid conflicts between modules?

Maxim Dounin mdounin at mdounin.ru
Mon Sep 23 12:49:02 UTC 2019


Hello!

On Sun, Sep 22, 2019 at 07:01:16PM -0400, ptcell wrote:

> I have a preaccess filter in my module that loads in the request_body with
> `ngx_http_read_client_request_body` (it basically scans the buffer for
> security violations, no modifications).  I don't discard the buffer and this
> module works fine when proxying POST requests or multiform data to a
> downstream reverse proxy.
> 
> If I try using a lua module that attempts to read the request body, too
> (like `resty.upload`), the module complains that request->request_body
> already exists and it cannot proceed.
> 
> Is there any way to reset request->request_body?  Just for a laugh I tried
> setting it to 0 and of course that doesn't work.  Barring that is there a
> way my module could read the request_body without causing a state change to
> the request struct?

You cannot "reset" a request body which is already read, as it is 
already read from the client, and there is no way to read it 
again.

In general, it is expected that the request body is being read 
when a module is going to use it.  And in most cases modules are 
able to use a body which is already read.  This is, for example, 
naturally happens when an upstream server error occurs, and the 
request is redirected to a different location with the error_page 
directive.

There are few exceptions though - in particular, it is not 
possible to use WebDAV module with body already read, as it uses 
body reading machinery to save the body to disk, and it is not 
possible to use non-buffered body reading more than once, as it 
doesn't save anything.

In this particular case I would first check if the module you are 
facing problems with needs to be fixed instead.  As outlined 
above, there are only a few valid reasons not to accept the body 
which is already read, and it is generally bad idea to introduce 
additional such cases.

Also you may want to consider re-writing your module to use 
request body filters instead.  This way your inspection code will 
be called only when ngx_http_read_client_request_body() is called 
elsewhere.  This approach is expected to be compatible with all 
uses of the client request body.  And it also make it possible to 
inspect buffers in memory even if they are going to be written to 
disk.

Just in case, an example request body filter can be found here:

http://mdounin.ru/hg/ngx_http_catch_body_filter_module/

-- 
Maxim Dounin
http://mdounin.ru/


More information about the nginx mailing list