nginx locations with similar prefixes - nginx

I'm trying to do configure nginx to serve different version of an Angular SPA, usually prefixed with "dev" or "prod" but having a location that is "dev" and "prod", but i don't want nginx to expose directories that are not configured (inside nginx.conf).
For example,
http://myserver/dev
http://myserver/dev-SomeFeatureBranch
If I use exact matching (= modifier), I can't reach anything below /dev or below /dev-SomeFeatureBranch, so that's not an option.
If I don't specify a modifier, I get prefix matching which kinda works but exposes other branches that I have not configured in my nginx.conf
For example, if i have a directory named "dev-SomePrivateBranch" in the same directory as my other Dev branches and I use the following configs:
location / {
root ../www;
}
location /dev {
alias ../dev;
}
location /dev-SomeFeatureBranch {
alias ../dev-SomeFeatureBranch;
}
I can effectively reach http://myserver/dev-SomePrivateBranch , since it matches "/dev" but i don't want to reach locations that i have not explicitly configured.
Add to that issues with trailing slashes, I'd like http://myserver/dev/ to work as well as http://myserver/dev
I'm sure this is super simple once you are used to nginx's ways, but i can't seem to get that working for the life of me.

You need to use a trailing / if you want your locations to refer to a single directory name rather than a random set of directory names that happen to begin with the same characters.
For example:
location / {
root ../www;
}
location /dev/ {
alias ../dev/;
}
location /dev-SomeFeatureBranch/ {
alias ../dev-SomeFeatureBranch/;
}
Note that the location and alias directives should both end with /.
The alias is probably unnecessary, as root ..; should work if the location name and directory name are the same.
For example:
location / {
root ../www;
}
location /dev/ {
root ..;
}
location /dev-SomeFeatureBranch/ {
root ..;
}
I do not like relative paths for root and alias, but it should still work if that's what you prefer.
The efficient solution to manage /dev and /dev/ is to redirect from one to the other. Nginx does this automatically if the directory exists. But in your case, it's not obvious as the initial URI is processed in the location / block. You can solve the problem with an explicit redirect.
For example:
location / {
root ../www;
}
location = /dev { return 301 /dev/; }
location /dev/ {
root ..;
}
location = /dev-SomeFeatureBranch { return 301 /dev-SomeFeatureBranch/; }
location /dev-SomeFeatureBranch/ {
root ..;
}
Finally, if the root is the same for all the location blocks, you may as well use a regular expression, in which case the entire solution can be wrapped up into one expression.
For example:
location / {
root ../www;
}
location ~ ^/dev(|-SomeFeatureBranch)($|/) {
root ..;
}
Note that the evaluation order of regular expression location blocks is significant. See this document for details.

Related

NginX redirect /service to /service/

I have two servicesr accessible via NginX. The web server configuration looks like this:
location /service1/ {
# process php files
}
location /service2/ {
proxy_pass http://127.0.0.1:9999/;
}
However, if one clicks on https://example.com/service1 (or 2) he gets a 404 error. There is no folder called "service1" (or 2) in the website root.
I would like links to "https://example.com/service1" to point to "https://example.com/service1/" (with trailing slash), possibly without specyfing a redirect for every service I have, i.e
location = /service1 {
return 301 https://$host/service1/;
}
location /service1/ {
# process php files
}
location = /service2 {
return 301 https://$host/service2/;
}
location /service2/ {
proxy_pass http://127.0.0.1:9999/;
}
I have already tried try_files $uri $uri/ =404;, but it seems to only work for real files and folders in the website root, no "virtual" subdirectories.
I am avoiding configurations like location /service { ... } because they seem more vulnerable.
Inside your location = blocks you need to generate an internal redirect to $uri/. You can achieve this using try_files or rewrite...last.
For example:
location = /service1 {
try_files nonexistent $uri/$is_args$args;
}
Notice that the internal redirection must be the last parameter. See this document for details.
Or:
location = /service1 {
rewrite ^(.*)$ $1/ last;
}
See this document for details.

how to make nginx location match path both with slash and without slash?

currently i have this location in my nginx file, it does not work with http://mydomain/ab/cd. How can i make the browser to go to the same page when user type both http://mydomain/ab/cd and http://mydomain/ab/cd/?
location /ab/cd/ {
}
The fastest, in terms of performance, is simply two exact locations:
location = /ab/cd {
...
}
location = /ab/cd/ {
...
}
You can try
location ~* ^/ab/cd(|\/) {...}
It is a prefix matching regex that checks if it has trailing slash or not.

Nginx multiple domains shared resources

I have the following folders:
/web/domain1/
/web/domain2/
/web/shared/
I want domain1 and domain2 to share static files from /web/shared/ but I am having trouble creating the mapping in nginx.
domain1: /assets/ mapped to /web/shared/
domain2: /admin/assets/ mapped to /web/shared/
server{
server_name domain1;
root /web/domain1/;
location / {
rewrite /assets/(.*) /web/shared/$1;
}
}
This gives me 404 error.
Define a location for URIs that begin with /assets/ (see this document for details). Use the alias directive, as the root directive cannot be used in this case (see this document for details).
For example:
location /assets/ {
alias /web/shared/;
}
This works
location /assets/(.*) {
alias /web/shared/$1;
}

nginx server: how to remove first directory from URL

Can anybody please help me to remove first directory name from URL?
My Image location is _data/hotel/3/15377/hotel_image.jpg
But Image path gets changed due to relative URL in code and it become to something like this.
example.com/france/_data/hotel/3/15377/hotel_image.jpg
example.com/usa/_data/hotel/3/15377/hotel_image.jpg
example.com/india/_data/hotel/3/15377/hotel_image.jpg
is their any possibilities to remove dynamic country name from above URL
If you want to rewrite only this particular URL, you can use this location block in your config:
location ~ /[a-z]+/_data/hotel/3/15377/hotel_image.jpg {
try_files /_data/hotel/3/15377/hotel_image.jpg;
}
If you want to rewrite all URLs which lead to /<country>/_data/..., you can use:
location ~ /[a-z]+/_data/(.+) {
try_files /_data/$1;
}
or for stricter URL checking:
location ~ /(?:france|usa|india)/_data/(.+) {
try_files /_data/$1;
}
#Ivan Shatsky's answer is great for files but also if we want to redirect a general url is better if you use the rewrite directive.
Depending where you define the rewrite directive you have two ways to implement it:
A. In the server context
server {
...
rewrite ^/[a-z]+/_data/(.+)$ /_data/$1 last;
...
}
B. In the location context
location ~ /[a-z]+/_data/(.+) {
rewrite ^/[a-z]+/_data/(.+)$ /_data/$1 break;
proxy_pass http://backend;
}
Teo, why did you change the flag to break?* Because, if this directive is put inside of a location context, the last flag might make nginx to run 10 cycles and return the 500 error.
Note:
Remember not add / at the end of the proxy_pass directive. This example wont work:
...
proxy_pass http://backend/;
...

Nginx one alias for multiple location directives

I have installed a project in a separate directory to make this project available on multiple domains
location ^~ /phpRedisAdmin/css/ {
alias /home/phpRedisAdmin/css/;
}
location ^~ /phpRedisAdmin/js/ {
alias /home/phpRedisAdmin/js/;
}
location ^~ /phpRedisAdmin/images/ {
alias /home/phpRedisAdmin/images/;
}
To prevent declaring a location directive for each one of the project subdirectory, is it possible to declare one location directive that would handle all the possible aliases instead?
I am looking for something like this (I don't know how to retrieve in the alias directive what is in the parenthesis):
location ^~ /phpRedisAdmin/(css|images|js)/ {
alias /home/phpRedisAdmin/>> what should I insert here? <</;
}
Problem solved, I ended up using this solution:
location ^~ /phpRedisAdmin/(css|images|js)$ {
alias /home/phpRedisAdmin/$1;
}
You should not use an alias directive, where a root directive will suffice. One solution would be to define a location block for all URIs which live below /phpRedisAdmin. For example:
location ^~ /phpRedisAdmin/ {
root /home;
location ~ \.php$ {
...
}
}
If you need to execute PHP scripts within this location, add a nested location (as shown above).
If you must use a regular expression location with an alias, you will need to capture the entire remainder of the URI. For example:
location ^~ /phpRedisAdmin/((?:css|images|js)/.*)$ {
alias /home/phpRedisAdmin/$1;
}
See this document for details.
You can try below
location ~* /phpRedisAdmin/(?P<folder>css|images|js)/ {
alias /home/phpRedisAdmin/$folder;
}

Resources