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

classic Classic list List threaded Threaded
2 messages Options
xrd
Reply | Threaded
Open this post in threaded view
|

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

xrd
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?

Thanks

Posted at Nginx Forum: https://forum.nginx.org/read.php?2,285672,285672#msg-285672

_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx
Reply | Threaded
Open this post in threaded view
|

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

Maxim Dounin
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/
_______________________________________________
nginx mailing list
[hidden email]
http://mailman.nginx.org/mailman/listinfo/nginx