nginx Sinatra head meta refresh 404 - nginx

For some reason, a page is forwarding to an nginx-served 404 page. The site is working except for this one page. On my landing page, I have the following in the header:
<meta http-equiv="refresh" content="5;URL=/second">
Even hard coding http://mydomain.local/second serves up the same 404.
This is a Sinatra deployment.
get "/second" do
#title = "my Title"
erb :index
end
I am thinking maybe my locations directive in nginx.conf is a bit screwy:
location / {
autoindex off;
try_files $uri $uri/ $uri/$request =404;
index /;
}
Anybody have any insight why Sinatra wouldn't capture the route and just serve up the file? Cheers.

Lets break this down:
autoindex off;
You don't need to specify this, it's off by default.
try_files $uri $uri/ $uri/$request =404;
Try and match requests to files in this order, serve the first one which matches. If none match, return 404. Your request is http://mydomain.local/second, so you are telling Nginx to look for:
webroot/second
webroot/second/
webroot/second/GET /second HTTP/1.1
Return 404
The index directive tells Nginx how to handle requests ending with a slash, you would normally specify files likely to be index files within your project, eg index.php, index.html etc. You don't really use this and try_files together as they serve a similar purpose.
Also worth noting that Nginx adds a trailing slash to any request which doesn't have one and doesn't end with a file extension, so it may also be the case that get "/second" do needs to change to get "/second/" do, as I doubt Sinatra ever sees the request without the trailing slash appended

Related

How can i use NGINX try_files without changing the browser location for the client?

I am using nginx try_files for Server-Side-Rendering. Since GET-parameters affect the resulting html, i want to use try_files to check if i have a prerendered version with the matching query string (file is saved at /posts/?page=5/index.html)
I have the following try_files statement in place:
try_files $uri/$is_args$args/ $uri $uri/ #ssr;
This works, but the client gets redirected to www.page.com/posts/?page=5 which is including the slash of the subdirectory i have. This results in the browser getting a 404 in the end, because that post does not exist.
How can i use try_files like i did, but without actually redirecting the client? To be clear: I want to serve files from whereever with try_files, but not actually let the client know which file is served, thats none of the browsers business in my case.
Is there a way to achieve this?

Nginx Reason for $uri/

I am looking at standard nginx server config for wordpress.
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
I understand the reason for $uri index.php$is_args$args
I do not understand the point of $uri/
I can see from nginx documentation "It is possible to check directory’s existence by specifying a slash at the end of a name, e.g. “$uri/”"
But I don`t get, what is the reason for returning a directory on request? Why would this be useful in a wordpress setup?
There is no such thing as "returning a directory on request". But trying to examine contents of a directory, and use them in order to satisfy a request - that's what it is here.
NGINX always has some non-empty value for the index directive (default is index.html), and that's essentially the files that NGINX will attempt to serve when trying a directory.
You don't really need $uri/ for WordPress if both conditions are met:
you don't have custom subdirectories/subsites which hold PHP files
you are using pretty permalinks
Removing $uri/ will result in saving one or more system stat calls (file existence check), so it is a performance improvement. The special case there would be a link /wp-admin. With try_files $uri /index.php$is_args$args it will be processed through /index.php, but Wordpress will do a proper redirect to /wp-admin/ (with slash).
And for what it's worth, you don't even need try_files if you have a habit of maintaining a well-structured website and intend to make it more optimized.

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 try_files works for all but one url

I have a simple dashboard for my site. Here is the directive:
location /dashboard {
try_files $uri /dashboard/index.php;
}
It works for all items after /dashboard. For example, /users or /pages - all CRUD operations work as expected.
The index.php file at /dashboard is my "controller". It parses the url and includes and runs scripts from there.
For example: /dashboard/group/edit/123456 works as expected and I get the edit page for group number 123456.
But when I post from that page to /dashboard/group/update, it serves /dashboard/group/index.php
So, in the first example, The edit page is loaded and the url at the top of the screen does not change.
In the second example, NGINX is CHANGING the url so my script cannot get the url parts to do the job.
I thought it may have something to do with POST, but I have other forms that use POST without issue.
In addition, or possibly a clue, try_files is returning /dashboard/group/index.php while the directive should return /dashboard/index.php.
Is there another NGINX file that could have so old code in it that is overwriting this domain's config?
I've been at this a few hours and have run out of ideas. Any thoughts?
* One More Clue *
When I BROWSE to /dashboard/group/update, NGINX shows the page as expected. It is only when I POST to that page that NGNIX sends me to /dashboard/group/index.php.
Again, at the very least, it should be sending me to /dashboard/index.php and NOT /dashboard/group/index.php.
You not send all after /dashboard try this:
location /dashboard {
try_files $uri /dashboard/index.php?$uri&$args;
}
OR
location /dashboard {
try_files $uri /dashboard/index.php?$query_string;
}
Nginx docs: https://nginx.org/en/docs/http/ngx_http_core_module.html#try_files
Instead of
location /dashboard {
try_files $uri /dashboard/index.php;
}
Try
location /dashboard {
index index.php; #adding this may work alone
try_files $uri /dashboard/index.php?$uri;
}
I have concluded that I have a cache problem. The location directive works on all items that I have not yet accessed.
So, my configuration - as described - works as it should.
I just have to figure out how to clear my cache ( which in NOT set up in NGINX that I can see!)
Thank you all who helped!

nginx match specific file from different folder on certain routes

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.

Resources