Nginx rewriting pushstate static resources wont load - nginx

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;
}

Related

NGINX Only path equals to without trailing slash and starts with path with trailing slash

I'm encountering an annoying error when it comes to my current NGINX app configuration.
I have a static web app which I am indexing on the path /admin/*. I want the index to be available on /admin, with and without a trailing slash, as well as available on a wildcard /admin/* (anything after the trailing slash).
The issue I am facing is that the index is accessable when appending anything after the admin path, for example /adminA/example.
The original NGINX configuration was as follows:
location /admin {
alias /home/user/app/static;
index index.html;
try_files $uri $uri/ /index.html;
}
The best I've been able to implement to stop this at the moment is as follows, however i'm sure it can be done more efficiently:
location = /admin {
alias /home/user/app/static;
index index.html;
try_files $uri $uri/ /index.html;
}
location /admin/ {
alias /home/user/app/static/;
index index.html;
try_files $uri $uri/ /admin/index.html;
}
The two location blocks are already efficient, but you could eliminate the redundant code in the first block by redirecting to the second.
Using an internal redirect will be invisible to the browser. For example:
location = /admin {
rewrite ^ /admin/ last;
}
location /admin/ {
...
}
Or use permanent instead of last for an external redirect, which will change the browser's address bar from /admin to /admin/. See the rewrite documentation.

Nginx Location based try files?

I was reading this page here https://help.sorryapp.com/en/articles/2783542-install-maintenance-pages-on-nginx that had a nifty idea of having a file present means nginx would route to a maintenance html page.
But then reading through the nginx docs it seems like if statements within the location block are not ideal, and instead to use try files. Whats the proper way to rewrite whats in the above to how nginx would like it? https://www.nginx.com/resources/wiki/start/topics/depth/ifisevil/
I assume is something like: but what about a rewrite?
try_files /my/file/path/maint.on
error_page 503 #maintenance_page;
location #maintenance_page {
rewrite ^(.*)$ /maintenance_page.html break;
?
UPDATE 1
this is my current config snippit, which happens to for some reason result in a 404 even through the maint.on file doesn't exist.
location / {
if (-f /opt/staytus/staytus/maint.on) {
return 503;
}
port_in_redirect off;
proxy_pass http://example.com:8787/;
}
error_page 503 #Performing-Maintenance;
location #Performing-Maintenance {
rewrite ^(.*)$ Performing-Maintenance.html break;
}
}
any thought on the issue?
As the same article states,
The only 100% safe things which may be done inside if in a location context are:
return ...;
rewrite ... last;
so the example you're found can be considered completely safe. (I'd say it is safe to use any directive from ngx_http_rewrite_module inside the if block which extends this list to break, return, rewrite and set). You can't do what you want with the try_files directive because it is requires at least one file argument before the last uri (or the name of named location or HTTP error code) argument which would be used if none of the files/directories from the list are actually exists. Well, I could imagine something like
location / {
try_files /maintenance.html #default;
}
location #default {
...
}
but you can't make it serving some location like
location = /maintenance.html {
...
}
, it would just return the contents of maintenance.html file. And if maintenance.html page would refer to some additional assets (like CSS, JS etc.) all user browser requests for that assets would lead to the maintenance.html contents (because that file exists and passed the try_files check). Just FYI, this directive
location / {
try_files $uri $uri/index.php =404;
}
...
location ~ \.php$ {
...
}
won't serve the $uri/index.php file through the PHP location handler (it just return its raw content), while this
location / {
index index.php;
try_files $uri $uri/ =404;
}
would.
However example you provided would have some performance impact (especially on the high-load servers) due to the extra stat kernel call made for every incoming request. I'd recommend this method of enabling maintenance mode with nginx.

NGINX - match all locations [duplicate]

I have developers who will be working on their local machines editing multiple Wordpress sites. I'd like to set up Nginx for them one time without the need for them to edit the config file in the future. Typically when Nginx is configured to host Wordpress, a location block such as this is included:
location / {
try_files $uri $uri/ /index.php$is_args$args;
} # End location
In our situation, each WP site will be in its own subdirectory. So when a developer needs to view a site, they'll go to a URL in their browser such as:
http://localhost/site1
http://localhost/site2
http://localhost/site3
What we would like is for the location directive above to include the subdirectories. As it is now, it only includes the root (http://localhost) and not the subs. I think this requires a wildcard or regex of some kind, but I'm not sure.
In other words, I think I'm looking for a location block like:
location /all-subdirectories {
try_files $uri $uri/ /whatever-subdirectory/index.php$is_args$args;
} # End location
Does this make sense or am I on the wrong track?
You could use a regular expression location to capture the first part of the URI, for example:
location ~ ^(/[^/]+) {
try_files $uri $uri/ $1/index.php?$args;
}
Or use a named location with one or more rewrite statements, for example:
location / {
try_files $uri $uri/ #rewrite;
}
location #rewrite {
rewrite ^(/[^/]+) $1/index.php last;
}

Regular Expression to fix broken URL's in Nginx

On my previous server that ran apache I had some htaccess rules that helped forward a certain pattern of URL's which were giving 404's to the fixed pattern.
Long time ago my URLS for my site were http://domainname/articlename and then I changed it to be http://domainname/category/articlename
Now the problem is the older links that google has are returning 404's and I want to intercept any URL that doesn't have a category and insert a fake category and then my wordpress installation can resolve the URL.
So I'm looking for a nginx solution to this problem which I presume will be in the config file somewhere that will take this URL
http://www.criticalhit.net/prey/ (which gives a 404)
and change it to
http://www.criticalhit.net/fixed/prey/
which then resolves properly.
Use a named location to perform the rewrite, although this simple rewrite can be accomplished efficiently using a return 301.
Place a regular expression location (after the PHP location block) to bypass excluded URLs. This does not need to include the static files which are served by the try_files statement.
For example:
root /path/to/root;
index index.php;
location / {
try_files $uri $uri/ #rewrite;
}
location #rewrite {
return 301 /category$request_uri;
}
location ~ \.php$ {
try_files $uri =404;
...
}
location ~ ^/(category|tags|feeds) {
try_files $uri $uri/ /index.php;
}
See this document for more.

nginx config with spa and subdirectory root

I always seem to have problems with nginx configurations. My SPA is located at /mnt/q/app (pushstate is enabled) and the frontend root is located at client/public. Everything should be mapped to index.html, where the app picks up the route and decides what to do.
Full path to the index is /mnt/q/app/client/public/index.html.
I think I ran out of options by now. No matter what I do, I just get a 404 back from nginx, I think the configuration is simple enought and have no clue what's wrong.
server {
listen 80;
server_name app.dev;
root /mnt/q/app;
location / {
root /client/public;
try_files $uri #rewrites =404;
}
location #rewrites {
rewrite ^(.+)$ /index.html last;
}
}
Any help is appreciated.
If nginx views the file system from the root, then the root should be set to /mnt/q/app/client/public, and not either of the two values you are using.
The last element of the try_files directive can be a default action (e.g. /index.html), a named location or a response code. You have a named location in the penultimate element - which will be ignored.
Your named location should work, but is unnecessary, as try_files is capable of implementing it more simply. See this document for more.
For example:
root /mnt/q/app;
location / {
root /mnt/q/app/client/public;
try_files $uri $uri/ /index.html;
}
location /api {
}
location /auth {
}
The $uri/ element will add a trailing / to directories, so that the index directive can work - you do not have to add it if you do not need it.

Resources