Nginx try_files ignore path - nginx

I have a location setup for images like:
location ~* ^/images/.+\.(jpg|jpeg|gif|png)$ {
try_files /disk/$uri /images?uri=$uri;
}
The $uri includes the images name. When I access /images/one/two/three/item.jpg, I want to exclude the images from the try_files. So accessing this should actually be trying /disk/one/two/three/item.jpg.
Any idea how I can exclude this first segment?

First I would wrap the regex location with a prefix location. This isolates the regex location and keeps it from conflicting with others. Your config will scale more smoothly as a result.
If there will only be images in this directory, then it's simpler to capture everything after /images/ and not worry about the file extension. You're then free to have a case sensitive match which is a little quicker.
location /images/ {
location ~ ^/images/(?<img_path>.+) {
try_files /disk/$img_path /images?uri=$img_path;
}
}

Related

What is difference between using $uri and $uri$args in try_files directive

For my other Angular apps, I am using the below config and everything seems to work fine.
location / {
try_files $uri$args $uri$args/ /index.html;
}
Now the one which I am working has nested folders within the dist folder.
And folder structure is something like:
dist \
-- assets
-- folder1
-- folder2
-- folder3
-- folder4
-- folder5
index.html
index.html
And the inner index.html is called with query params, and the url will be like - <ip>/folder1/folder2/index.html?a=1&b=2&c=3. But this is returning the fallback index.html at the root location. Later, I changed the above location block like this and it started working properly.
location / {
try_files $uri $uri/ /index.html;
}
So I am not clear why the first location block didn't work. And I can't find anything in docs - try_files
All of the parameters of a try_files statement except the last parameter are looking for filenames in the local file system.
So given the URI /foo/bar, the term $uri$args will search for a local file at /path/to/root/foo/bar, and if it does not exist will move on to the next term or the default clause at the end of the statement.
In the above case, $args is empty. However, given the URI /foo/bar?baz, the term $uri$args will search for a local file at /path/to/root/foo/barbaz.
I don't know why anyone would use $uri$args or $uri$args/ as file terms on a try_files statement, but there may well be a legitimate use case.
The last parameter of a try_files statement is special. It can be a status code (for example =404), a named location to branch to, or a URI.
In the case of a URI, Nginx will internally redirect to that URI. A typical example might be /index.php$isargs$args - in this case it is perfectly legitimate to append the $args parameter, as we are creating a new URI and keeping the original argument string.
See this document for details.

How do I correctly use try_files when looking in two different directories for files to serve?

I'm quite new to Nginx so I might be misunderstanding of what try_files can do.
For my local development set up I have multiple installations that will each be accesible via their own subdomain. These installations are being migrated into a new folder structure but I still want to have the ability to support both at the same time. When pulled via git the new full path looks like this :
/home/tom/git/project/v3/[installation]/public/
The old structure goes 1 directory deeper namely as follows:
/home/tom/git/project/v3/[installation]/workspace/public
Where installation is variable according to the installation name and the /public folder will be the root for nginx to work from.
The root is determined by the subdomain and is extracted via regex like so:
server_name ~^(?<subdomain>[^.]+)\.local\.project\.test;
So far I've managed to get all this working for one of the folder structures but not both at the same time. My Nginx configuration for this local domain looks like this. Below is what I've tried but just can't seem to get working. As soon as I pass the #workspace named location as fallback for try_files it always defaults to 404.
index index.html index.htm index.nginx-debian.html index.php;
server_name ~^(?<subdomain>[^.]+)\.local\.project\.test;
root /home/tom/git/project/v3/$subdomain/public/;
location / {
try_files $uri #workspace =404;
}
location #workspace {
root /home/tom/git/project/v3/$subdomain/workspace/public/;
try_files $uri =404;
}
I have also tried shortening the root and passing the following parameters to try_files
root /home/tom/git/project/v3/$subdomain;
location / {
try_files /public/$uri /workspace/public/$uri =404;
}
But this still defaults to a 404, with a $uri/ as a third parameter there it will emit a 403 forbidden trying to list the directory index of the root.
I hope someone can provide some advice or an alternative as to how to approach this issue I am facing. If I need to provide additional data let me know,
Thanks in advance.
The named location must be the last element of a try_files statement.
For example:
location / {
try_files $uri #workspace;
}
location #workspace {
...
}
See this document for details.
The $uri variable includes a leading /, so your constructed pathnames contain a // which may be why they fail.
For example:
location / {
root /home/tom/git/project/v3/$subdomain;
try_files /public$uri /workspace/public$uri =404;
}

Nginx URL routing

I think this is kind of basic stuff, but I'm struggling to find proper guide that would explain these things:
I have a index.php file and nginx config so that https://dev.something.com works ok.
But I need to change nginx config so that that address produces blank page, and index.php only works from https://dev.something.com/lists. I could put index.php inside lists directory, but isn't there more subtle solution?
And here's the hard part:
Users should be able to access
https://dev.something.com/lists/userName
https://dev.something.com/lists/userName/listName
userName and listName should be used as GET-parameters.
Can anyone help how I could achieve this kind of config with nginx?
You're asking a few (relatively basic) questions, and I would suggest you start with their free e-book https://www.nginx.com/blog/announcing-oreillys-new-book-nginx-a-practical-guide-to-high-performance/
You can define where nginx looks for index files with the root clause, and though they normally use the URL context relative to the server's root, it can be override in each location.
http://nginx.org/en/docs/http/ngx_http_core_module.html#root
You can use portions of URLs as variables, which can be passed as paramters too.
location = /lists { # '=' will match exactly, no trailing url
root /path/where/index.php/lives;
try_files $uri /index.php;
}
location /lists { # this will match anything under that url
rewrite ^/lists/(\d+)/?$ /lists?user=$1; # matches username
rewrite ^/lists/(\d+)/(\d+)/?$ /lists?user=$1&list=$2; # matches username/list
}
location /{ #everything else
root /path/where/index.html/lives; #index.html is empty file.
try_files $uri /index.html;
}

Nginx, render a file with dynamic name

I have a cachebreaker that produces css filenames as this one: /css/vendor.min.333311133.css.
I want nginx to answer request with a previous version with the latest.
Note that I will only have one version of that file in the directory... so I'm thinking of a rule like the following, but it's not working:
location ~* /css\/vendor\.min\.(.*)\.css {
try_files $uri ~* /css\/vendor\.(.*)\.css =404;
}
Does anybody knows if nginx support dynamic names in try_files? Or should I use another directive? Any ideas?
If your build process is able to do this, just put the file there without the cachebreaker part and do this:
location ~* /css\/vendor\.min\.(.*)\.css {
try_files /css/vendor.min.css =404;
}
In theory you can use a regex capture inside the location, but since the old version number would be in there, it would not help.

nginx same location but with different directives

Trying to see if this is possible.
We have an app and a wordpress install.
Is it possible to use 2 locations for the same folder but under different circumstances. Example..
http://domain.com/subfolder/ - This shows the APP
http://domain.com/subfolder/anything - This shows WP permalink
Right now, we have it so
http://domain.com/subfolder (without the /) shows the app
http://domain.com/subfolder/ (witht the /) shows WP.
This does work, but would it be possible to have it so, it will only show WP IF the URL contains text after subfolder/*
Current Nginx conf:
location ^~ /knowledge {
root /opt/domain.com/public/;
try_files $uri #backend;
}
location /knowledge/ {
index index.php index.html index.htm;
root /opt;
include /etc/nginx/php-wpsc.conf;
try_files $uri $uri/ /knowledge/index.php?q=$uri&$args;
}
Obviously it makes sense to keep the location /knowledge/ block for WordPress, as that matches the majority of cases, with just one case that needs to be overridden.
A specific URI can be taken away from that location block by using a location block with a higher precedence. See this document for details.
One possibility would be an exact match location block:
location = /knowledge/ {
rewrite ^ /knowledge last;
}
Or possibly, change your existing location ^~ /knowledge block from a prefix location to a regular expression location, making the trailing / optional.
location ~ ^/knowledge/? { ... }
Note that this changes the order of evaluation of this location block, so there may be side-effects that need to be considered.

Resources