There are lots of posts out there on the topic of fixing the Request-URI Too Large error in NGINX, but this post is about how to generate such a response in order to avoid proxying requests with too long urls to a backend server.
The Problem
We recently had some really long request URLs coming through NGINX, with over 2000 characters! Those requests triggered an error response on our IIS hosted ASP.NET application – at first, on one backend server, then on the second one. This lead NGINX to believe that currently no backend servers are available for processing request which resulted in requests being dropped. Ouch!
Hence, our motivation to avoid passing requests with too long urls down to our backend/upstream servers.
Some Background
Since we don't have any URLs in our application whose path segment exceed the default limit of 260 characters, there is no need to change the respective maxUrlLength attribute on the <httpRuntime> element. There's also a default value of 2048 characters for the length of the query string, defined in the maxQueryStringLength attribute, that might be of interest.
So I set out to tell NGINX to drop requests with path segments longer than 260 chars or query strings longer than 2048 chars.
The Solution
We'll be looking at the $request_filename and $query_string variables and verify their length is less than or equal to the limits implemented in our application server.
At first, I tried to find a way to return the length of these variables' values but I couldn't find any way to that inside the NGINX configuration file.
So I was left with testing those variables against some value or… a regular expression.
That's right, a regular expression will tell us if our variables exceed our length limits:
if ( $request_filename ~* "^.{261,}$" ) {
return 414;
}
if ( $query_string ~* "^.{2049,}$" ) {
return 414;
}
We use the regex quantifier {n,} to match n or more occurrences of the previous expression, which in our case is a . (dot) meaning any character.
Roundup
We've put these two if directives at the server level of our configuration. We now successfully avoid to pass requests with too long urls to our application servers.