Nginx - multiple/nested IF statements - nginx

What i want to do:
Check if request comes from Facebook
Check if URL is like domain.com/2
If above conditions are true - show content from /api/content/item/$1?social=1
If above conditions are false - show "normal page"
It is a single page app. Before my changes configuration looked like this (and it worked):
location / {
root /home/eshlox/projects/XXX/project/project/assets/dist;
try_files $uri $uri/ /index.html =404;
}
I've tried to use if statements:
location / {
set $social 1;
if ($http_user_agent ~* "facebookexternalhit") {
set $social UA;
}
if ($uri ~* "^/(\d+)$") {
set $social "${social}URL";
}
if ($social = UAURL) {
rewrite ^/(\d+)$ /api/content/item/$1?social=1;
}
root /home/eshlox/projects/XXX/project/project/assets/dist;
try_files $uri $uri/ /index.html =404;
}
With this configuration everything works as i expected only if both conditions are true or false.
If one of conditions is true and the second is false (or vice versa) then nginx always returns status 404.
I have found "IfIsEvil" on nginx site, i've tried to use mapping (can i use mapping in this case?) but still i can't resolve this problem.
Any ideas?
Best regards.

There is good article about common pitfalls in nignx wiki.
First, I've moved root directive to server level. Second, location is the best way to check urls. So I rethink your requirements as
if location consist of digits
and request from facebook
we have to rewrite url, and the result is:
root /home/eshlox/projects/XXX/project/project/assets/dist;
location / {
try_files $uri $uri/ /index.html;
}
location ~ "^/\d+$" {
if ($http_user_agent ~* "facebookexternalhit") {
rewrite (.+) /api/content/item$1?social=1;
}
try_files $uri $uri/ /index.html;
}
Also, there is almost no reason to have =404 after /index.html in try_files directive.

Related

nginx rewrite specific folder to php and arg

Am trying to redirect
domain.tld/blog/read.php?article=first-article to domain.tld/blog/first-article
What I tried and didn't work resulting in redirect to domain.tld/first-article
location "^blog/([^/]+)/?$" {
try_files /$uri /$uri/ /blog/read.php?article=$1;
}
location /blog {
rewrite ^/blog/?$ /blog/read.php?article=? last;
rewrite ^/blog/([-a-zA-Z0-9_]+)/$ /blog/read.php?article=$1? last;
}
location ~ "^/blog/([^/]+)/?$" {
try_files /$uri /$uri/ /blog/read.php?article=$1;
}
Thinking the issue comes from my other parts in the config and mainly second location from below
server {
...
...
location ~ "^/([^/]+)/?$" {
try_files $uri $uri/ /device.php?name=$1;
}
location ~ "^/([^/]+)/([^/]+)/?$" {
try_files $uri $uri/ /device.php?name=$1&crversion=$2;
}
...
Any pointers would help a lot
Cheers
So the fast answer is actually the fact that my config was fine first time, yet nginx config is read top bottom with first match being the one that is used.
So in the end the "fix" was adding the blog part upper in the site config
location ~ "^/blog/([^/]+)/?$" {
try_files /$uri /$uri/ /blog/read.php?article=$1;
}

Defaulting to 404 when file doesn't exist in nginx

Here is my nginx setup:
location / {
root /var/www/web-app/public;
index index.html index.htm;
try_files $uri $uri/ /index.html;
default_type "text/html";
}
location /profile_images {
try_files $uri $uri/ =404;
}
The question is on that second block. It is a directory full of images. When I look up an image based on a user id, I may or may not have the image. If not, I want a 404 error. Based on the above I am getting a 404 on all images now. I have tried both 404 and =404.
The first location is my api which works fine.
I look up the images (in html) with src='/profiles_images/***.png'
For what it is worth, I am using reactjs.
You are missing a root directive for the second location block. Where several location blocks share the same value for root, it is usual practice to place the root statement in the enclosing server block so that all location blocks inherit the same value. For example:
server {
...
index index.html index.htm;
root /var/www/web-app/public;
location / {
try_files $uri $uri/ /index.html;
}
location /profile_images {
try_files $uri $uri/ =404;
}
}
See this document for more.

Wordpress Multisite with nginx. Match subdirectories within location

I have multiple WordPress sites running in subdirectories.
Everything works great, but I'm looking to simplify my nginx configuration.
At the moment, when I add a location, I need to add an entry to my server {} configuration for the specified directory.
location / {
try_files $uri $uri/ /index.php?q=$args;
}
location /site1 {
try_files $uri $uri/ /site1/index.php?q=$args;
}
location /site2 {
try_files $uri $uri/ /site2/index.php?q=$args;
}
location /site2 {
try_files $uri $uri/ /site3/index.php?q=$args;
}
location /site4 {
try_files $uri $uri/ /site4/index.php?q=$args;
}
I tried adding a regex to match the subdirectory, but seem to have a problem with it.
location /([_-0-9a-zA-Z]/?) {
try_files $uri $uri/ /$1index.php?q=$args;
}
does not appear to do the trick. In theory that should match a subdirectory, or nothing, and be able to let me add new directories without having to touch the nginx configuration.
Any pointers would be appreciated.
#jedifans pointed out how to get the regex to work
Thanks. That did the trick on any pages, but when I go to / it just tries to download the index.php.
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
fastcgi_pass php70;
fastcgi_keep_conn on;
}
location ~ ^/([_\-0-9a-zA-Z]*/?) {
try_files /$1$uri /$1$uri/ /$1index.php?q=$args;
}
However when I go to domain.com/site1/ i get a download of the index.php not the homepage. What's missing?
I think you are missing the following from your new location block, the ~ operator that says to nginx that it's a regular expression. Try:
location ~ ^/([_-0-9a-zA-Z]*/?) {
A few regex tweaks too, ^ to say it must begin with / and * to match more than one of those characters within [ and ]
Edit: after your question update, try the following try_files directive:
try_files $uri $uri/ /$1/index.php?q=$args;
$uri should work without the matched string prepended and I have added a / in between the matched query and the index.php;
Also make sure to have index index.php; at server{} level.

nginx try_files without any files - internal redirect

Given:
location ~ /foo/ {
try_files $uri $uri/ /foohandler.py;
}
try_files: "If none of the files were found, an internal redirect to the uri specified in the last parameter is made" 1.
If I know $uri and $uri/ will never exist, how do I always do an internal redirect to /foohandler.py without using try_files?
Using try_files /foohandler.py is invalid syntax. What is the proper equivalent? return? rewrite?
location ~ /foo/ {
rewrite ^ /foohandler.py break;
}
You can still use try_files. It requires more than one parameter, so just add a 404 code to avoid the syntax error:
location ~ /foo/ {
try_files /foohandler.py =404;
}
On a side note, if your uri always begins with /foo/ then a prefix location would be better:
location /foo/ {
try_files /foohandler.py =404;
}

why does ^~ not stop processing routing rules in nginx?

So I've got 2 routes, and the first one doesn't stop the route matching, as the docs say it should:
location ^~ /p/ {
root /www/domain.com/;
try_files $uri $uri/ /path/index.html;
}
location ^~ /v/ {
root /www/domain.com/;
try_files $uri $uri/ /path/index.html;
}
location ^~ / {
root /www/domain.com/php_www/;
try_files $uri $uri/ /index.php;
location ~* \.(?:php|html)$ {
try_files $uri =404;
fastcgi_pass 127.0.0.1:9000;
include /etc/nginx/fastcgi_params;
}
auth_basic "Staging";
auth_basic_user_file /www/.htpasswd;
}
So if I have a url like this:
http://domain.com/p/1234567890
It matches the last route and not the first route. The problem surfaced because one of our guys added a page to the application:
http://domain.com/privacy
This was picked up by the FIRST route?? Which is where the problem is coming from.
The problem I'm having is with ^~. In the docs, it says that once this matches, it will stop matching, however the last route is always the one that loads.
Any ideas?
Upgraded to latest nginx, and re-ordered some of the directives and everything is working now.

Resources