nginx location with wildcard to proxy_pass - nginx

I understand a few basic concepts of nginx, but this one is beyond me.
This directive below works perfectly fine
location /a/web/8b5d3df315/assets {
proxy_pass https://thisdomain.com/a/assets;
}
However, the 8b5d3df315 needs to be a wildcard (or 'any') since I have many different entities needing to point to the same uri https://thisdomain.com/a/assets
I have tried this which returns a 404.
location /a/web/([A-Za-z0-9]+)/assets {
proxy_pass https://thisdomain.com/a/assets;
}
As well as the one below, which returns a: "proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except"
location ~ ^/a/web/([A-Za-z0-9]+)/assets {
proxy_pass https://thisdomain.com/a/assets;
}
This answer felt close to my problem https://stackoverflow.com/a/53354944/1864622 but I don't think is quite a match.
Does anyone know how to go about this?

Related

nginx proxy_pass doesn't work right when concatenating to variable

I have an NGINX server running as a reverse proxy for a service I host. I tried configuring it with this:
set $upstream_nzbget http://nzbget:6789;
location /nzbget/api/ {
proxy_pass $upstream_nzbget/;
}
But the proxy_pass doesn't work properly when I try to add the slash / to the end of $upstream_nzbget. If I change it to this, it works properly:
location /nzbget/api/ {
proxy_pass http://nzbget:6789/;
}
So I think it has something to do with variables in proxy_pass. In the first case (the one that isn't working), I'm not really sure what the URL ends up being. I haven't found a way to log the final URI that gets used by proxy_pass.
Can someone explain why the first case isn't working? What is the proper solution? Note that I need to keep the variable in proxy_pass so it uses the resolver.
Side note: I use a trailing slash in my location block because otherwise I get a 404 when I use this URL:
domain.com/nzbget/api/api:password/xmlrpc
This is why I use /nzbget/api/ instead of /nzbget/api.
EDIT 1
I played around with this some more, and I found that this also doesn't work:
location /nzbget/api/ {
set $upstream_nzbget http://nzbget:6789/;
proxy_pass $upstream_nzbget;
}
This one is really strange. It's the same string, the only difference is using a variable vs a string literal. I'm not doing any string concatenation here. I'm not sure why there's a behavioral difference.
EDIT 2
This SO question might be the same issue, but it has no helpful answers.
You need to pass $request_uri when using it with variable. It's there in the docs somewhere.
It'll be something like:
location /nzbget/api/ {
set $upstream_nzbget http://nzbget:6789$request_uri;
proxy_pass $upstream_nzbget;
}

How to block a specific URL in NGINX webserver

I want to block a specific URL but I am not able to do this.
The URL that should be blocked is example.com/clientarea/?dxx_g=dddd.
But the following url should still work - example.com/clientarea.
I tried the following:
location ^~ /clientarea/ {
return 444;
}
But if I do this it will block all connections to /clientarea.
I hope you can help me or advise me how to make this possible.
The location and rewrite statements test a normalized URI which does not include the ? and anything following it.
The $request_uri variable contains the entire URI. Test this variable using an if or map directive.
For example:
if ($request_uri = /clientarea/?dxx_g=dddd) {
return 444;
}
You can also use regular expressions. See this document for more. See this caution on the use of if.
If you have a number of URIs to block, you should consider using a map instead.

Rewrites in Nginx

I need to enter a bunch or rewrites in my conf file in Nginx. I am not very experienced so I copied what I found before, example.
location = /index.php/blog/blog/xxx/yyy/ {
return 301 /index.php/blog/xxx/yyy/;
}
However I was told that the best way is the following:
location ^~ /index.php/blog/blog/xxx/yyy/ {
rewrite ^/index.php/blog/xxx/yyy/;
}
Which one id the correct one?
The first one is more correct, both location as well as the return -wise, and it'll work faster.
FWIIW, your second snippet looks like it's missing a space in the rewrite after ^, and it's also less efficient, both location as well as rewrite-wise.
References:
http://nginx.org/r/location
http://nginx.org/r/return
http://nginx.org/r/rewrite

How can I have same rule for two locations in NGINX config?

How can I have same rule for two locations in NGINX config?
I have tried the following
server {
location /first/location/ | /second/location/ {
..
..
}
}
but nginx reload threw this error:
nginx: [emerg] invalid number of arguments in "location" directive**
Try
location ~ ^/(first/location|second/location)/ {
...
}
The ~ means to use a regular expression for the url. The ^ means to check from the first character. This will look for a / followed by either of the locations and then another /.
Another option is to repeat the rules in two prefix locations using an included file. Since prefix locations are position independent in the configuration, using them can save some confusion as you add other regex locations later on. Avoiding regex locations when you can will help your configuration scale smoothly.
server {
location /first/location/ {
include shared.conf;
}
location /second/location/ {
include shared.conf;
}
}
Here's a sample shared.conf:
default_type text/plain;
return 200 "http_user_agent: $http_user_agent
remote_addr: $remote_addr
remote_port: $remote_port
scheme: $scheme
nginx_version: $nginx_version
";
Both the regex and included files are good methods, and I frequently use those. But another alternative is to use a "named location", which is a useful approach in many situations — especially more complicated ones. The official "If is Evil" page shows essentially the following as a good way to do things:
error_page 418 = #common_location;
location /first/location/ {
return 418;
}
location /second/location/ {
return 418;
}
location #common_location {
# The common configuration...
}
There are advantages and disadvantages to these various approaches. One big advantage to a regex is that you can capture parts of the match and use them to modify the response. Of course, you can usually achieve similar results with the other approaches by either setting a variable in the original block or using map. The downside of the regex approach is that it can get unwieldy if you want to match a variety of locations, plus the low precedence of a regex might just not fit with how you want to match locations — not to mention that there are apparently performance impacts from regexes in some cases.
The main advantage of including files (as far as I can tell) is that it is a little more flexible about exactly what you can include — it doesn't have to be a full location block, for example. But it's also just subjectively a bit clunkier than named locations.
Also note that there is a related solution that you may be able to use in similar situations: nested locations. The idea is that you would start with a very general location, apply some configuration common to several of the possible matches, and then have separate nested locations for the different types of paths that you want to match. For example, it might be useful to do something like this:
location /specialpages/ {
# some config
location /specialpages/static/ {
try_files $uri $uri/ =404;
}
location /specialpages/dynamic/ {
proxy_pass http://127.0.0.1;
}
}
This is short, yet efficient and proven approach:
location ~ (patternOne|patternTwo) {
#rules etc.
}
So one can easily have multiple patterns with simple pipe syntax pointing to the same location block / rules.
This worked for me
upstream nextjs-fp {
server nextjs-frontend:3000;
}
server {
listen 80;
location ~* .(_next|profile|orders)$ {
proxy_pass http://nextjs-fp;
}
}

Nginx Location directives, what is the effect of trailing or prepended slashes?

I.e., what is the difference between
location somefolder {
}
and
location somefolder/ {
}
and
location /somefolder {
}
and
location /somefolder/ {
}
I know it's kind of a silly question but honestly sometimes I get myself confused, a concise answer would be nice!
Found my own answer.
The first two configurations will not match anything, because every location starts with a "/". So they are basically invalid locations. A commenter on Server Overflow mentioned this and it proved to be correct.
The second two, for most purposes, are equivalent, in that NGINX will 301 redirect the third to the fourth. So a request for http://somedomain/somefolder will be redirected to http://somedomain/somefolder/. If you really have a location called /somefolder, such as a file literally called that, then you could create a location with the "=" operator, which forces an exact match, so
location = /somefolder {
}
For best practice just always use the /somefolder/ format unless you really need the exception I just mentioned.

Resources