nginx force serve local file, instead of web URL - nginx

I'm trying to authenticate user, then serve the requested file.
URL: http://example.com/stream/asd.m3u8
Static file: /stream/asd.m3u8 (/ = Linux filesystem's root)
location ~ /stream/(.*)\.m3u8 {
# authentication happens here, but commented out
for debugging, and had the results below;
alias /stream/;
# 403 Forbidden (the directory and contents has chmod 777)
rewrite /stream/(.*)\.m3u8 /stream/$1;
# Infinite loop (curl: (47) Maximum (50) redirects followed)
rewrite /stream/(.*)\.m3u8 /stream/$1 break;
# 404 Not Found (in web root, that file doesn't exist)
try_files /stream/$1.m3u8 =404;
# 404 Not Found
try_files /stream/$1.m3u8 =505;
# 505
}
I think nginx treats /stream/asd.m3u8 as a web URL.
How can I force it to treat /stream/asd.m3u8 as a local file?
Also, what could cause the 403 on alias directive?
Thanks!

The URI is the same as the pathname, which means that the document root is /. The document root is set using the root directive. See this document for details.
To set the correct document root for any URI that begins with /stream/ use:
location /stream/ {
root /;
}
If you have other files in this location, and only want to serve those ending with .m3u8, you could use your existing regular expression location block:
location ~ ^/stream/.*\.m3u8 {
root /;
}
See this document for more.
The alias directive is not necessary here, in which case the root directive is preferred. To use alias inside a regular expression, you must capture the entire URI. See this document for details.

Related

Nginx serve files on specific location from specific folder

I want NGINX to serve serve files from a location within a server.
As an example, I would like the url http://domain/ss/image.png to serve the file located within /home/data/screenshots/image.png
So far, I have attempted to use a regex in this manner
location ~ ^/ss/(.*) {
root /home/data/screenshots;
add_header content-type "image/png";
try_files $1 /$1;
}
however it appears that this location is never reached, being handled by the location spefcified to / (which in my case is a redirect).
I am not flexible with renaming/changing any of the file structure of the project and want to achieve this result with just the NGINX config modification.
As described by Richard's comment on the question, it appears that my regex approach was correct, however my issue was the usage of the try_files function.

NGINX – Serving multiple SPA’s on a single server

We have a development server with lots of single page apps that also handle routing in the frontend.
Normally for a single page app I would assume you need to configure something like:
location /some/path {
try_files $uri $uri/ /index.html?$args;
}
Now on our development server it is quite a lot of work to re-configure nginx for every small test app people put on there.
I want to:
Serve the file if found
Serve the index.html file if the path is a folder
If not found, go back one folder and try look for index.html and serve that
Try previous step until you find an index.html file
Stop trying when you reach the defined root path e.g. /some/path, if that doesn’t have an index.html, return the folder content
If some sort of while loop is not possible (performance is less critical since it's for development purposes only), I could limit it to up to 6 folders back. That should cover most SPA's.
Example:
Let's say I have a single page app on:
/some/path/my-app
And one goes to:
/some/path/my-app/page1/subpage2/id3
It should try:
/some/path/my-app/page1/subpage2/id3 (no match)
/some/path/my-app/page1/subpage2/id3/index.html (no match)
/some/path/my-app/page1/subpage2/index.html (no match)
/some/path/my-app/page1/index.html (no match)
/some/path/my-app/index.html (MATCH !)
P.S. I'm mainly a front-end developer, my nginx knowledge is very limited.
You can use a named location as the last parameter of a try_files statement to perform an internal rewrite to climb up the directory tree. Nginx will limit this to about 10 iterations before declaring a redirection loop.
For example:
root /path/to/root;
index index.html;
location / {
try_files $uri $uri/ #rewrite;
}
location #rewrite {
rewrite ^/(.+/)?. /$1 last;
}
The index and try_files directives handle looking for index.html, and the rewrite statement truncates the URI by removing one or more characters following a /.

nginx serve index file from subfolders

I would like to serve an index file from a root folder and one from a subfolder from root.
My nginx server conf looks as follows:
server {
listen 80;
server_name localhost;
root /data/;
index index.html index.htm index.txt;
location / {
}
location /a {
alias /data/a/;
}
}
and my directory structure looks as follows:
/data/:
a index.txt
/data/a:
index.txt
If I then do curl localhost, I get the contents of the file /data/index.txt.
But curl /localhost/a gives me a 301.
curl localhost/a/index.txt works.
Why can't I access my index.txt with curl /localhost/a ?
I tried using a root instead of alias in the location /a block and also tried to specify the index.txt for location /a, but no success.
I see similar posts, e.g.
Nginx location configuration (subfolders)
but couldn't yet find the answer.
The index directive works with URIs that end with a /:
So the URI / gives you the contents of /index.txt and /a/ gives you the contents of `/a/index.txt.
If you provide Nginx with a URI of a directory (but without a trailing /), the default behaviour is to redirect to the same URI, but with a trailing /.
This is just how the index directive works. See this document for details.
If you want something other than default behaviour you will have to do it manually using try_files. See this document for details.
For example, to return the contents of an index.txt file by providing the URI of the directory without a trailing /, use:
root /data;
location / {
try_files $uri $uri/index.txt =404;
}
Note that the location /a { ... } block is not necessary in either this example, or the example in your question.

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 match location for root path and all other paths separately

I am running Play framework server behind nginx server. At the root path, I am serving static website and all other paths should be redirected to the Play server. I have the following default.conf file in /etc/nginx/conf.d (The system is RHEL 6.7)
# to match the root path only to serve static website
location = / {
root /usr/share/nginx/html;
index index.html index.htm;
# try_files $uri $uri.html $uri/ /index.html;
}
# to match the cms login page
location /cms/ {
proxy_pass http://localhost:9000/;
}
# to match all the requests from the cms
location / {
proxy_pass http://localhost:9000/;
}
However, this configuration doesn't match the root path request. It gives 404 error. However, if I remove the third location rule, then it serves the static page at the root path.
Also, I noticed that first time I tried this, it worked. But now, it's not working any more. Please help.
The result you are getting is most likely due to the 2nd and 3rd location blocks not having "index" directives set. Except for well understood specific reasons, such as overriding the default index file type(s), the "index" should always be set at least within the server context or, preferably, within the http context. Similarly, the "root" directive should be set in the server context.
With your config, when a request hits the 3rd location block, there is no information your what to do with it. Actually, the 2nd block should not be needed from what you have described.
Also, as you are proxying to what appears to be another webserver, you need to ensure that this has the equivalent of "index" and "root" set.
Not sure exactly how the backend you are using works with respect to these. If not configurable there, then you must ensure that that every request hitting it has the URI spelt out fully.
To start with, depending on how exactly things are set up on your server, I will move the "index" and "root" directives up to the "server" level

Resources