Different url rewriting according to locations - nginx

I really don't find any documentation I find clear about URL rewriting (I can't understand it, as I unexpectedly find the documentation really hard to read for a non-native).
I'm looking for a way to rewrite all routes that matches /*\.(js|png|jpg|css|ttf|xml)$/ toward path/media/ and try existance of file then return it if exists, else 404 not found
then if it begins with /ajax/ redirect all of it toward path/ajax/index.php
else redirect all of it toward path/www/index.php
I don't quite understand how I should do it, for now I created 3 locations /media/, /ajax/ and /www/ but I don't know if it is the right way to use rewrite and not return, or are the locations the correct way to do it.
I don't really understand what I've written in my sites-enabled/file regarding fastcgi. is this a interpretor path ?
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
If I get it right, it means "if it ends with .php, and it exists in hierarchy, then execute it".
And I don't know if I should put that kind of stuff for each location that has to deal with php (/www/ and /ajax/), especially since I'm going to do some routing for both. Moreover, I don't know if it should be done that way.

The simplest PHP configurations use a common root directive which is inherited by the location blocks, and in your case would be:
root path;
This means that /www/index.php and /ajax/index.php are both processed by the location ~ \.php$ block.
The default action can be defined by the try_files directive within a location / block:
location / {
try_files $uri $uri/ /www/index.php;
}
If you need a different default action for URIs which begin with /ajax, add a more specific location:
location /ajax {
try_files $uri $uri/ /ajax/index.php;
}
If you do not want your media URIs to begin with /media you can override the root for one specific location:
location ~* \.(js|png|jpg|css|ttf|xml)$ {
root path/media;
}
The fastcgi_split_path_info and fastcgi_index directives are unnecessary in your specific case. The include fastcgi_params; statement should be placed before any fastcgi_param directive to avoid the latter being inadvertently overridden:
location ~ \.php$ {
try_files $uri =404;
include fastcgi_params;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
See the nginx documentation for details.

Related

How to add conditional pattern matching rules with IP restriction to Nginx?

I would like to configure a rule such that anything with a pending + will be redirect to a 404 page except for a certain allow IP.
eg.
If IP is 111.111.111.111, http://domain.com/12345+ will be processed (via php block)
Any other condition will return 404 not found
This rule should take precedence before the php block.
location ~ "^/([0-9a-zA-Z]{5})\+$" {
allow 111.111.111.111;
deny all;
try_files $uri $uri/ /index.php.php$is_args$args;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php-fpm-www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
The above solution works for me, even though it shows a 403 forbidden instead of giving me 404 not found if coming from an unauthorized IP.
I would appreciate if someone can show me how to display an internal 404 page or even redirect to an external URL when 404 occurs.

Nginx rewrite to make a "personal URL"

I'd like to be able to make "personal URL" for our users (Facebook like), which is of course a dynamic strings. it needs to be in the root of the site, and that is why I'm having a big headache with it.
The requirements that I have are:
1. I need
www.example.com/John.Doe (it can be a-zA-Z0-9_-.)
and rewrite it to:
www.example.com/profile?id=John.Doe
2. I also need the site scripts to be extension less like (which I was able to do, with the great people here, using "$uri.php$is_args$query_string;"):
so
www.example.com/login
will go to:
www.example.com/login.php
I tried a lot of things, but I just can't get the right formula to make it work.
This is my configuration, right now:
location / {
try_files $uri $uri/ $uri.php$is_args$query_string;
}
location ~ \.php$ {
if ($request_uri ~ ^/([^?]*)\.php(\?.*)?$) {
return 301 /$1$2;
}
try_files $uri =404;
include /etc/nginx/fastcgi_params;
fastcgi_pass 127.0.0.1:9001;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
You have an overlapping namespace for your extension-less scripts and your personal URLs, so you need to test for the presence of the $uri.php file before rewriting it to profile.php.
So rather than rewrite the URI in the first try_files directive (as you have it now), it may be better to use a named location block to process the PHP file without having to rewrite it first.
Like this:
location / {
try_files $uri $uri/ #php;
}
location #php {
try_files $uri.php #rewrite;
include /etc/nginx/fastcgi_params;
fastcgi_pass 127.0.0.1:9001;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location #rewrite {
rewrite ^/([a-zA-Z0-9_.-]+)$ /profile.php?id=$1 last;
}
location ~ \.php$ {
if ($request_uri ...) { ... }
try_files $uri =404;
include /etc/nginx/fastcgi_params;
fastcgi_pass 127.0.0.1:9001;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
The first block serves static files. The second block processes extension-less PHP files (if and only if they exists). The third block performs a rewrite to profile.php (which does not need to be extension-less, as it is not exposed to the client). The fourth block processes normal .php URIs and includes your $request_uri fix.
Note that fastcgi_index is redundant in both this and the original configuration.
For more details, here are some links to the nginx documentation for the location, try_files and rewrite directives.

fastcgi - passing information to scripts

I`m new with nginx and I dont know even what should I look for. My task is to force (I think it is) fastcgi to pass information (PATH_INFO) to the scripts. I have been told that I should add something in block after location ~ .php$ . Adding before fastcgi_pass xxx;
fastcgi_param PATH_INFO $fastcgi_path_info;
would made that happened ?
My location part config file looks like that:
location ~ ^/backend\.php/(.*)$ {
try_files $uri /backend.php?$1;
}
location ~ \.php$ {
# Zero-day exploit defense.
# http://forum.nginx.org/read.php?2,88845,page=3
# Won't work properly (404 error) if the file is not stored on this server, which is entirely possible with php-fpm/php-fcgi.
# Comment the 'try_files' line out if you set up php-fpm/php-fcgi on another machine. And then cross your fingers that you won't get hacked.
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass xxx;
}

Redirect in nginx [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I know that there are a lot of similar questions but I tried several solutions and I can't find correct solution.
I have no idea about nginx. I have only simple task: redirect all addresses /backend.php/* to /backend.php in one concrete application/website. I used * to express anything. Now /backend.php/* path is redirected to /index.php.
This is my config file:
server {
server_name _;
rewrite ^ $scheme://mysite.com$request_uri redirect;
}
upstream md {
#this should match value of "listen" directive in php-fpm pool
server unix:/var/run/md.php5-fpm.sock;
}
server
{
server_name .mydomain.eu .mydomain.du;
access_log /var/log/nginx/mydomain.access.log;
error_log /var/log/nginx/mydomain.error.log;
root /home/md/;
include conf/restrictions.conf;
include conf/wordpress.conf;
# Pass all .php files onto a php-fpm/php-fcgi server.
location ~ \.php$ {
# Zero-day exploit defense.
# http://forum.nginx.org/read.php?2,88845,page=3
# Won't work properly (404 error) if the file is not stored on this server, which is entirely possible with php-fpm/php-fcgi.
# Comment the 'try_files' line out if you set up php-fpm/php-fcgi on another machine. And then cross your fingers that you won't get hacked.
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
#NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# fastcgi_intercept_errors on;
fastcgi_pass md;
}
}
=======UPDATE===========
conf/wordpress.conf:
# WordPress single blog rules.
# Designed to be included in any server {} block.
# This order might seem weird - this is attempted to match last if rules below fail.
# http://wiki.nginx.org/HttpCoreModule
location / {
try_files $uri $uri/ /index.php?$args;
}
# Add trailing slash to */wp-admin requests.
rewrite /wp-admin$ $scheme://$host$uri/ permanent;
# Directives to send expires headers and turn off 404 error logging.
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off; log_not_found off; expires max;
}
# Uncomment one of the lines below for the appropriate caching plugin (if used).
#include global/wordpress-wp-super-cache.conf;
#include global/wordpress-w3-total-cache.conf;
## Pass all .php files onto a php-fpm/php-fcgi server.
#location ~ \.php$ {
# # Zero-day exploit defense.
# # http://forum.nginx.org/read.php?2,88845,page=3
# # Won't work properly (404 error) if the file is not stored on this server, which is entirely possible with php-fpm/php-fcgi.
# # Comment the 'try_files' line out if you set up php-fpm/php-fcgi on another machine. And then cross your fingers that you won't get hacked.
# try_files $uri =404;
#
# fastcgi_split_path_info ^(.+\.php)(/.+)$;
# #NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
#
# include fastcgi_params;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
## fastcgi_intercept_errors on;
## fastcgi_pass wp-php;
#}
Ok. Nginx request rules operate on the regular expressions first from more specific to less specific. Then operate on the non regular expression rules.
In your case I honestly don't know in what order is
rewrite /wp-admin$ $scheme://$host$uri/ permanent;
processed so please comment it out while we sort the other issue.
The following rule is the less specific and has no regex, so it will be processed last
location / {
try_files $uri $uri/ /index.php?$args;
}
which is fine. It's a fallback for any request that's not php or either not a real url (for example, wordpress nice urls).
The following rule has regex and is very specific, so it will be processed first than any other and as you see, it affects static files:
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off; log_not_found off; expires max;
}
And lastly, the php rule has regex and is less specific than the previous one, so it will be processed for requests that end in .php unless they have a static file extension (which won't happen because if they do, then they won't match the "end with php" thing).
location ~ \.php$ {
...
fastcgi_pass md;
}
So at this point, if you issue a request that points to /backend.php with or without query string, and there is a file with that name, it will fall under the .php rule and pass to your php-fpm backend.
If you issue a request that points to /backend.php/something and there isn't a folder with that name, it will fall under the first rule, and since there isn't a backend.php folder, it will be redirected (by the try_files directive) to index.php.
Long story short. If you need that urls that have backend.php be redirected to backend.php, you need to set another rule that's more specific than the .php one.
EDIT: just to discard possible errors, please comment out the line in which you're including conf/wordpress.conf. Instead, your second server block should read
server
{
server_name .mydomain.eu .mydomain.du;
access_log /var/log/nginx/mydomain.access.log;
error_log /var/log/nginx/mydomain.error.log;
root /home/md/;
include conf/restrictions.conf;
location / {
try_files $uri $uri/ /index.php?$args;
}
# Directives to send expires headers and turn off 404 error logging.
location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off; log_not_found off; expires max;
}
location ~ ^/backend\.php/(.*)$ {
try_files $uri /backend.php?$1;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
include fastcgi_params;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass md;
}
}

Short-circuit logic in Nginx conf (would like to override a location)

I have mediawiki installed. All is right in the world except for when I try to alias a external directory (webalizer web stats). I see that Nginx passes off the request to /usage/* to PHP/Mediawiki. I don't want that. I literally want everything under /usage/ to point to my alias and nothing else. Completely separate from Mediawiki code and functionality.
# in no way related to Mediawiki. I just want to serve this as static HTML.
location /usage {
alias /var/www/webalizer/wiki.longnow.org/;
}
# This answers to anything, which may be my problem
location / {
try_files $uri $uri/ #rewrite;
index index.php;
}
# A special rewrite to play nicely with Mediawiki
location #rewrite {
rewrite ^/(.*)$ /index.php?title=$1&$args;
}
# PHP, nom nom nom
location ~ \.php$ {
include fastcgi_params;
fastcgi_index index.php;
fastcgi_pass unix:/tmp/php-fastcgi.socket;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
I was hoping that listing the /usage location directive ahead of the rest would short-circuit the system, but I have been spoiled by Django ;)
To stop Nginx from processing further location directives, it should be prefixed by ^~.
I think you will still want a try_files falling back to a 404 response inside the location.
location ^~ /usage {
alias /var/www/webalizer/wiki.longnow.org/;
try_files $uri $uri/ =404;
}
See http://wiki.nginx.org/HttpCoreModule#location for reference.

Resources