Nginx allow only root and api locations
Solution 1
Here it is:
location = / {
# would serve only the root
# ...
}
location /api/ {
# would serve everything after the /api/
# ...
}
You need a special '=' modifier for the root location to work as expected
From the docs:
Using the “=” modifier it is possible to define an exact match of URI and location. If an exact match is found, the search terminates. For example, if a “/” request happens frequently, defining “location = /” will speed up the processing of these requests, as search terminates right after the first comparison.
Solution 2
You could use an if
statement to test for $request_uri
being equal to root, or starting from /api/
, all within the same location
statement, or within the server
context:
if ($request_uri !~ ^/$|^/api/) {return 403;}
However, alternatively, due to the way processing is done, the most efficient way with nginx would be to have 3 separate location
directives, each handling one of the 3 possibilities — the /
root exact match, the /api/
prefix, and then all the other stuff, as per http://nginx.org/r/location.
Additionally, if you also require that the root location prohibit the the query string, you can either test for $is_args
(or $args
/$query_string
as appropriate), or, outright test whether the whole request URL is exactly /
or whether it has anything more to it (note that location
directives themselves don't operate based on $request_uri
, but based on $uri
, which are slightly different).
location = / {
# handle root
if ($request_uri != "/") {
# ensure $query_string and $is_args are not allowed
return 403 "<h1>403: query_string not allowed</h1>\n";
}
}
location /api/ {
# handle the /api/ prefix
}
location / {
# handle everything else
return 403;
}
Deena
Updated on June 11, 2022Comments
-
Deena almost 2 years
I have a server configured as a reverse proxy to my server. I want to reject all the requests except to two locations, one for root and another the api root.
so the server should only allow requests to the given paths
example.com/ (only the root) example.com/api/ (every url after the api root)
The expected behaviour is that the server should reject all the below possibilities.
example.com/location example.com/location/sublocation example.com/dynamic-location
my current nginx configuration,
server { # server configurations location / { # reverse proxy configurations } }
How do I set up this configuration?
-
ffeast about 6 yearswhy do you suggest to use if + regexp for this case?
-
cnst about 6 yearsI do not suggest using if + regex, I simply provide it as an option, in case that's what you want.
-
Lethargos over 2 yearsBut how will the if conditional ever match if the location references only the root url? I don't think that's correct.
-
Lethargos over 2 yearsTo say nothing of the fact that you're using if inside a location block - which is highly controversial: nginx.com/resources/wiki/start/topics/depth/ifisevil
-
cnst over 2 years@Lethargos it's literally explained in parenthesis why
if
within thelocation = /
does work! Theifisevil
page, likewise, explains that my code is 100% correct and 100% safe! Please kindly don't downvote answers you don't understand just because you think they might not work, especially after many others have confirmed the answer does work. Also, please kindly don't link to pages you haven't read just because the title is catchy. :-) -
Lethargos over 2 yearsI am not dogmatic, I started testing it myself directly and I still thought you were wrong for a while until I figured a url that would match the if. Unfortunately I cannot rescind my vote now because of a seemingly random rule: "You last voted on this answer Sep 21 at 12:14. Your vote is now locked in unless this answer is edited."