I am trying to serve a jekyll blog on nginx.
The files in the build directory should be reachable via the following routes:
- index.html -> /
- 1.0/
- index.html -> /1.0/
- foo/
a.html -> /1.0/foo/a/
b.html -> /1.0/foo/b/
c.html -> /1.0/foo/c/
- bar/
1.html -> /1.0/bar/1/
2.html -> /1.0/bar/2/
I tried to use the try_files directive in nginx but it always calls the fallback although the files are available. Here is the config:
location ~* ^(.+)/$ {
try_files $uri /$1/index.html /$1.html =404;
}
If I remove the 404 fallback it only works for the last value.
So my question is: What's the best way to configure nginx for serving static files like this?
If I remove the 404 fallback it only works for the last value.
This is because the last parameter of try_files directive should be an HTTP error code or an URI to try if the file not found. In your case nginx assumes it is an URI.
Try this:
location ~ ^(?<path>/.*/)(?<file>[^/]+)/$ {
try_files $uri $path$file.html $uri/ =404;
}
If you want to serve http://example.com/1.0/foo/a requests similar to http://example.com/1.0/foo/a/, change regex to ^(?<path>/.*/)(?<file>[^/]+)/?$.
Related
I made a next.js export into the out folder.
Folder structure is:
out
index.html
terms.html
privacy.html
I set up nginx to serve files from this folder:
server {
root /var/www/myproject/out;
index index.html index.htm index.nginx-debian.html;
server_name myproject.com;
location / {
try_files $uri $uri/ /index.html;
}
}
The main page (index) opens fine. Navigation from within the app to urls like myproject.com/privacy works fine. The problem is if I try to open these links directly, it will serve the main page (index) instead of the actual pages, since those urls don't exist in the folder. The only way to open the privacy page directly is adding the html extension to the url: myproject.com/privacy.html.
How to configure nginx to serve the actual page myproject.com/privacy.html when someone enters the myproject.com/privacy url?
Issue is in try_files.
As current configuration includes:
/ (which default route to index.html at root path)
index.html
/index.html
test/*.html
To access pages route path name without extension i.e., /privacy that format should be included in try_files insdie location /
Try this:
try_files $uri $uri.html /$uri /index.html
I needed a 2nd location block because of the way NextJS does ids in the url. NextJS will have files like [id].html or whatever.
location / {
try_files $uri $uri.html /$uri /index.html;
}
location ~* /(.*)(\d+)$ {
try_files $1/[id].html /$1/[id].html /index.html;
}
So I needed the 2nd block to catch urls of the form /whatever/etc/5 and redirect nginx to /whatever/etc/[id].html
Wondering about the difference between doing:
location / {
try_files $uri $uri/ =404;
}
And doing:
location / {}
They both seem to serve files\folders only if they exist, or returning 404 error page if they don't.
There is no difference, try_files $uri $uri/ =404; is exactly the default nginx behavior:
Check if $document_root$uri is a file, and if it is, serve the request with the contents of this file;
Check if $document_root$uri is a directory, and if it is, serve the request with the first found index file from this directory. If no index files found, nginx will return directory list if you have autoindex on in your nginx config or HTTP 403 Forbidden error otherwise;
Return HTTP 404 Not found if $document_root$uri nor a file neither a directory.
Advantage of the try_files directive is that you can specify additional files/directories to check and select what to do if none of them are found (jump to another URI / jump to some named location / return any HTTP error code).
However try_files may give you some performance penalty depending of your settings, read this article by #DanilaVershinin for more details.
Trying to configure nginx to find files from subfolder. Code from nginx documentation:
location / {
try_files $uri $uri/index.html $uri.html =404;
}
request "/" opens file index.html - it's ok
request "/folder" opens file /folder/index.html - ok
but request "/folder/file" as I suggest, should open /folder/file.html - but it returns 404
Please help me configure nginx try_files setting correctly so nginx can find file.html in "folder" directory when "/folder/file" request is received
I have an angularjs app, it has a blog as well. This url shows all blog posts under
http://example.com/blog/
And specific blog posts under
http://example.com/blog/example-blog-post-title
Now i'm precompiling HTML of blog posts for SEO purposes and i want to serve them completely separately from my main app like this:
...
root "/home/ubuntu/client/public";
location / { ## Handle default requests ##
try_files $uri $uri/ /index.html;
}
location /blog { ## serve precompiled blog HTML
alias /home/ubuntu/bloghtml;
try_files $uri.html $uri/ index.html;
}
...
And this works, by going to http://example.com/blog/example-blog-post-title nginx successfully serves file /home/ubuntu/bloghtml/example-blog-post-title.html
However the issue is that in this case nginx doesn't correctly route blog post list under http://example.com/blog/ to my main angular app, i get error 403 on that URL.
I tried changing location /blog to location /blog/ in conf file, this makes the http://example.com/blog/ work, howewever i get 404 errors on http://example.com/blog/example-blog-post-title
How can i make this work for both cases?
If you change the location from /blog to /blog/ you need to remember to change alias from /home/ubuntu/bloghtml to /home/ubuntu/bloghtml/. The alias and location need to have the same ending, otherwise the calculated pathnames are wrong.
I try to avoid using alias and try_files in the same block because of some known issues. You might consider making the last directory in the path blog so that you can use root instead.
I presume that your angular app is /index.html, in which case your try_files statement is incorrect. The $url/ will cause it to try /blog/index.html (assuming you have an index directive in force) and index.html is missing a leading /.
I would suggest you try:
location /blog {
alias /home/ubuntu/bloghtml;
try_files $uri.html /index.html;
}
but consider designing out the alias directive too.
I am trying to get nginx to work with a pushstate based uri handled by react-router.
Everything works fine until I try to F5 on a second level uri example.com/MyApp/users.
My static resources are in example.com/MyApp/resources.
The problem is that nginx is trying to load my resources in example.com/MyApp/users/resources whenever I try to access directly (or F5) the users's view.
Here is my nginx conf :
location ~ ^/MyApp/ {
try_files $uri /MyApp/index.html last;
}
I am new to nginx so I don't really know how everything works...
EDIT :
I changed my conf to this:
location / {
if (!-e $request_filename){
rewrite ^(.*)$ /MyApp/index.html break;
}
}
Now accessing to example.com/MyApp/users works but example.com/MyApp/users/ doesn't.
With client side app paths:
/
/foo
/foo/bar
/foo/bar/baz
/foo/bar/baz/123
/tacos
/tacos/123
Use nginx configuration:
server {
listen 80;
server_name example.com;
root /var/www/example.com;
gzip_static on;
location / {
try_files $uri $uri/ /index.html;
}
# Attempt to load static files, if not found route to #rootfiles
location ~ (.+)\.(html|json|txt|js|css|jpg|jpeg|gif|png|svg|ico|eot|otf|woff|woff2|ttf)$ {
try_files $uri #rootfiles;
}
# Check for app route "directories" in the request uri and strip "directories"
# from request, loading paths relative to root.
location #rootfiles {
rewrite ^/(?:foo/bar/baz|foo/bar|foo|tacos)/(.*) /$1 redirect;
}
}
This configuration will work within a pushState "directory" such as example.com/foo/bar/baz/213123 and resolve static files at relative paths like js/app.js to example.com/js/app.js instead of example.com/foo/bar/baz/js/app.js.
For cases with directory depth beyond the first level such as /foo/bar/baz, note the order of the directories declared in the #rootfiles directive: the longest possible paths need to go first, followed by the next shallower path /foo/bar and finally /foo.
See this related answer to a similar question regarding Backbone.
I think you will have to do something like this:
location ~ ^/MyApp/ {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ /index.html =404;
}
location ~ ^/MyApp/resources {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ /resources/index.html =404;
}