How to avoid sending incomplete request data to backend if 499 error

Maxim Dounin mdounin at mdounin.ru
Tue Nov 19 17:48:32 UTC 2019


Hello!

On Tue, Nov 19, 2019 at 10:29:37AM -0500, feanorknd wrote:

> Hello...
> 
> Few days ago I have had this problem... let me explain with log lines:
> 
> X.X.X.X - - [16/Nov/2019:04:36:17 +0100] "POST /api/budgets/new HTTP/2.0"
> 200 2239 "----" "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2 like Mac OS X)
> AppleWebKit/605.1.15 (KHTML, like Gecko) GSA/86.0.276299193 Mobile/15E148
> Safari/605.1" Exec: "2.190" Conn: "10" Upstream Time: "2.185" Upstream
> Status: "200"
> 
> X.X.X.X - - [16/Nov/2019:04:36:55 +0100] "POST /api/budgets/new HTTP/2.0"
> 499 0 ""----"" "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2 like Mac OS X)
> AppleWebKit/605.1.15 (KHTML, like Gecko) GSA/86.0.276299193 Mobile/15E148
> Safari/605.1" Exec: "0.147" Conn: "1" Upstream Time: "0.142" Upstream
> Status: "-"
> 
> In the first line, there is nothing of interest... just the POST request was
> completely fine.
> 
> In the second request, there was a client disconnection and POST request was
> not complete, as given by the 499 logged error.
> 
> The problem was:
> - the incomplete POST data was sent from nginx to the backend fastcgi server
> somehow.
> - that code did process the incomplete request data and generated a corrupt
> entry in certain database... another history.

In no particular order:

- By default, nginx will pass the request to the backend server 
  only when it's completely received from the client, including 
  the request body.  You can change things by explicitly using 
  "fastcgi_request_buffering off;", but this shouldn't change things 
  much as long as your backend is properly written.

- Any backend server is expected to verify if it received complete 
  request, as the connection between nginx and backend can be 
  broken from unrelated reasons, such as network issues.

- An incomplete request will result in 400, not 499.  The 499 
  error means that the request was complete, but the client closed 
  connection before the response was generated.

Given the above, most likely what you've seen was a connection 
close by the client after sending a complete request.  For 
example, this might have happened when nginx was sending the 
request body to the backend.

By default, if the client closes the connection - nginx closes the 
connection with the backend to let the backend know that no 
further request processing is needed.  A properly written backend 
is expected to handle this correctly, as it is anyway have to 
check the request integrity.

If for some reason your backend cannot cope with this, there is 
the fastcgi_ignore_client_abort directive to control this 
behaviour (http://nginx.org/r/fastcgi_ignore_client_abort).

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


More information about the nginx mailing list