why does ^~ not stop processing routing rules in nginx? - 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.

Related

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.

How do I remove the file extension from URLs in nginx?

Let's say I have a file named careers.php, how do I serve this file when they click a link that goes to http://example.com/careers without the file extension for both .html and .php files with nginx?
Please note that the solution has to account for query strings. For instance, the URL may be http://example.com/careers?lang=fr.
Also, I'd like the solution to also try subdirectories as well. For instance; if my folder structure on the server is /views/careers.php, I want http://example.com/careers to still serve /views/careers.php.
My current configuration looks like the following:
server {
listen 80 default_server;
root /usr/share/nginx/landing-page;
index index.php index.html;
server_name example.com;
location / {
try_files $uri $uri/ =404;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
A common solution uses try_files with a named location. The existing location ~ \.php$ block is used to process .php files. Also avoid any if statements.
location / {
try_files $uri $uri/ #rewrite;
}
location #rewrite {
rewrite ^ $uri.php last;
}
location ~ \.php$ {
try_files $uri =404;
...
}
You can use try_files:
try_files $uri $uri.php $uri/ =404;
I know that this is an old post, but I feel like this was never perfectly explained or explained using the most simple solution.
Here is an example of how I accomplished this for a React Application served using nginx for my Portfolio Website hosted on Digital Ocean.
When simplified it's super easy to accomplish. The location block should look like this.
//Originally my location block was set up like this
location /chatgpt-homepage.html {
root /var/www/myportfoliowebsite.com/html/chatgpt-app-homepage/build;
}
//What needs to happen is you need to remove the .html from your location
//and
//Add try_files $uri $uri.html $uri/ =404; underneath your root section of code
//New Location Block example below
location /chatgpt-homepage {
root /var/www/myportfoliowebsite.com/html/chatgpt-app-homepage/build;
try_files $uri $uri.html $uri/ =404;
}

NGINX: main location block overriding sub directory location?

I've read a moderate amount of the documentation for location blocks, but I dont have much experience with RegEx so I am a bit lost on how to pull off what I am trying to do. The following nginx config will probably explain what I want to do better than I can word it:
server {
server_name example.com www.example.com;
root /var/www/;
index index.php;
location /blog/ {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}
location / {
try_files $uri #uwsgi;
}
location #uwsgi {
include uwsgi_params;
uwsgi_pass unix:/tmp/uwsgi.sock;
}
}
example.com/ is being served by a bottle app through uwsgi, and so all things under this location should be routed to the bottle app and handled there. This is working fine as expected, however I am lost on how to add an 'exception' to the location rule so that example.com/blog, and everything under it ../sub1/sub2 etc. are not directed to the bottle app, but infact handled by wordpress and its PHP magic.
This seems like it should be very simple to set up, but it's proving very difficult to google simple solutions to these sort of problems, as everyone seems to bloat thier 'tutorial' configurations with tons of non-essentials that confuse a beginner.
This may need some tweaks, but you should probably use a nested location block:
server {
server_name example.com www.example.com;
root /var/www;
index index.php;
location /blog/ {
try_files $uri $uri/ /blog/index.php?$args;
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}
}
location / {
try_files $uri #uwsgi;
}
location #uwsgi {
include uwsgi_params;
uwsgi_pass unix:/tmp/uwsgi.sock;
}
}
Notice that the default URI is changed to /blog/index.php which is hopefully where all of your WordPress files are located.

Nginx - multiple/nested IF statements

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.

Resources