Nginx configuration for rewrite rule - nginx

So I have this configuration at the moment in nginx:
autoindex off;
location / {
try_files $uri $uri.html $uri/ #extensionless-php;
index index.html index.htm index.php;
}
location #extensionless-php {
rewrite ^(.*)$ $1.php last;
}
# pass PHP scripts to FastCGI server
#
location ~ \.php$ {
include snippets/fastcgi-php.conf;
# With php-fpm (or other unix sockets):
fastcgi_pass unix:/var/run/php/php7.1-fpm.sock;
# With php-cgi (or other tcp sockets):
#fastcgi_pass 127.0.0.1:9000;
}
Now, I want to get something 'special'. I want to get an url (http://project2.local/camera?camera_id=1) to be rewritten as http://project2.local/camera/1 I've tried this code;
location / {
rewrite ^/?camera\.php$ /camera/%1? redirect;
}
location /camera {
rewrite ^/camera/([^/]*)$ /camera.php?camera_id=$1 break;
}
but that downloads something empty when I navigate to that place.. What am I doing wrong here?

Try:
location /camera {
rewrite ^/camera/([^/]*)$ /camera.php?camera_id=$1 last;
}
The rewrite...break will prevent the camera.php URI being processed by the PHP location. You need to use last as per your existing configuration. See this document for details.
You also added: location / { rewrite ^/?camera\.php$ /camera/%1? redirect; }, but it seems wrong and superfluous for a number of reasons:
You cannot have two location / blocks (perhaps you meant you added the line of code to the existing location / block)
I do not recognise the %1 term (the value of the parameter would be $arg_camera_id)
It will never match anything (URIs ending with .php are processed by the PHP location)

Related

Remove file extension and keep parameters on nginx

I'm trying to make url on my server seo friendly.
Original: /face.php?name=hello-stackoverflow123
Desired: /face/hello-stackoverflow123
I made those little configs:
location / {
try_files $uri $uri.html $uri/ #extensionless-php;
index index.html index.htm index.php;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}
location #extensionless-php {
rewrite ^(.*)$ $1.php last;
}
Problem 1: I can't find a config to keep the parameters it gives me always 404 (so I get 404 if I try face/hello-stackoverflow123
Problem 2: If I have a file faces.php it will open if I try/faces, but if I open faces.php it won't redirect to /faces

nginx rewrite & parameter full-url and file extensions

I will try to be brief. I have the following nginx rewrite url:
rewrite ^/(.*)?$ /index.php?completeURL=$1 last;
I want a url like:
http://mywebsite.com/http://www.otherwebsite.com/dir1/dirx/article.php&id=2&category=1
request:
http://mywebsite.com/index.php?completeURL=http://www.otherwebsite.com/dir1/dirx/article.php&id=2&category=1
Currently the nginx rule have a problem. Example: If the parameter contains a .php extension he looks for that file on my server.
Example: http://mywebsite.com/dir1/dirx/article.php
How can I solve this problem in your opinion?
UPDATE:
here the nginx configuration (and rewrite) files:
(config) https://gist.github.com/ivanionut/cc53c9de372b932c3937d9394d3b448c
(rewrite) https://gist.github.com/ivanionut/4df3ad9b858a54ae01461ab078adffb6
The simplest solution (assuming that the server does nothing else other than serve index.php) is to remove the usual location ~ \.php$ block and perform a rewrite ... break; in the same block as the fastcgi_pass. There are a number of ways of achieving this, including:
location / {
rewrite ^/(.*)?$ /index.php?completeURL=$1 break;
fastcgi_pass ...
...
}
An alternative strategy is to perform the rewrite only if a local file does not already exist, but you need to ensure that .php files are tested too. For example:
location / {
try_files $uri $uri/ #rewrite;
}
location ~ \.php$ {
try_files $uri #rewrite;
fastcgi_pass ...
...
}
location #rewrite {
rewrite ^/(.*)?$ /index.php?completeURL=$1 last;
}

How to combine rewrites with different roots in location blocks

I'm struggling to understand how to control rewrites to PHP scripts when the location blocks that do the rewrites require different roots.
Here's the simplified example. My catch-all front controller must be in the web root, but the firewall.php script must not be.
The purpose of this is to provide gated access to download files not under the root.
server {
# Requests for media forced through firewall script outside web root
# /path/to/secure-area/firewall.php
#
location ^~ /downloads/ {
root /path/to/secure-area;
rewrite ^/.+$ /firewall.php last;
}
# Regular requests bootstrap front controller under web-root
# /path/to/web-root/index.php;
#
location / {
root /path/to/web-root;
index index.php
if ( -e $request_filename ) {
break;
}
rewrite ^.+$ /index.php last;
}
# Execute PHP via php-fpm
# rewrites hitting this are not mapping request_filename properly
#
location ~ \.php$ {
if ( !-f $request_filename ) {
return 404;
}
include /usr/local/nginx/conf/fastcgi_params;
fastcgi_pass unix:/tmp/php.sock;
fastcgi_index index.php;
}
}
The obvious solution is having a common root, but this is not possible in my situation. I cannot place the secure location under the web root and the web root must stay as-is.
It looks as if the root directive is only effective within the location block that defines it. The rewrites are individually working fine, but when the ~ \.php block is hit, the root is lost.
I'm obviously doing it wrong, so how should I achieve this?
Untested, but something like this ought to help you. It uses the http://wiki.nginx.org/XSendfile to serve the protected content from a different root. Also uses try_files which is a much better pattern for Front Controllers.
server {
# More here: http://wiki.nginx.org/XSendfile
#
# To serve /downloads/some.zip
# get php to set the http header:
#
# X-Accel-Redirect: /downloads/some.zip
#
# and then the file /path/to/secure-area/downloads/some.zip
# will be sent by nginx
location /downloads/ {
internal;
root /path/to/secure-area;
}
location / {
root /path/to/web-root;
index index.php
try_files $uri $uri/ /index.php;
}
# make sure you read http://wiki.nginx.org/Pitfalls
location ~* \.php$ {
try_files $uri =404;
fastcgi_pass unix:/tmp/php.sock;
fastcgi_index index.php;
include /usr/local/nginx/conf/fastcgi_params;
}
}

Nginx deny doesn't work for folder files

I'm trying to restrict access to my site to allow only specific IPs and I've got the following problem: when I access www.example.com deny works perfectly, but when I try to access www.example.com/index.php it returns "Access denied" page AND php file is downloaded directly in browser without processing.
I do want to deny access to all the files on the website for all IPs but mine. How should I do that?
Here's the config I have:
server {
listen 80;
server_name example.com;
root /var/www/example;
location / {
index index.html index.php; ## Allow a static html file to be shown first
try_files $uri $uri/ #handler; ## If missing pass the URI to front handler
expires 30d; ## Assume all files are cachable
allow my.public.ip;
deny all;
}
location #handler { ## Common front handler
rewrite / /index.php;
}
location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler
rewrite ^(.*.php)/ $1 last;
}
location ~ .php$ { ## Execute PHP scripts
if (!-e $request_filename) { rewrite / /index.php last; } ## Catch 404s that try_files miss
expires off; ## Do not cache dynamic content
fastcgi_pass 127.0.0.1:9001;
fastcgi_param HTTPS $fastcgi_https;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params; ## See /etc/nginx/fastcgi_params
}
}
That is because your deny/allow rule applies to just one location.
Remove that and try:
server {
listen 80;
server_name example.com;
root /var/www/example;
if ($remote_addr != "YOUR.PUBLIC.IP") {return 403;}
...
}
As the test is outside any specific locationblock, it will apply to all cases.
Note also that IF is not evil here since it just "returns".
OK, so I've found the solution. Nginx processes the most exact regex which in this case is the regex for php files. To make the config work all further locations must be defined within / location rule except for #handler (you cannot put under any rule - only as root)
server {
listen 80;
server_name example.com;
root /var/www/example;
location / {
index index.html index.php; ## Allow a static html file to be shown first
try_files $uri $uri/ #handler; ## If missing pass the URI to front handler
expires 30d; ## Assume all files are cachable
allow my.public.ip;
deny all;
location ~ .php/ { ## Forward paths like /js/index.php/x.js to relevant handler
rewrite ^(.*.php)/ $1 last;
}
location ~ .php$ { ## Execute PHP scripts
if (!-e $request_filename) { rewrite / /index.php last; } ## Catch 404s that try_files miss
expires off; ## Do not cache dynamic content
fastcgi_pass 127.0.0.1:9001;
fastcgi_param HTTPS $fastcgi_https;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params; ## See /etc/nginx/fastcgi_params
}
}
location #handler { ## Common front handler
rewrite / /index.php;
}
}

Nginx location behave with and without location regex

To include my small project (not based on one of the known frameworks) into existing website, I've added the following config to Nginx
server {
listen 80 default_server;
server_name localhost;
access_log /var/log/nginx/dev.access.log;
error_log /var/log/nginx/dev.error.log;
root /var/www;
index index.php;
[...]
location /www.my-project.com {
alias /var/www/www.my-project.com/web;
index index.php;
if (-f $request_filename) { break; }
rewrite ^(.*)$ /www.my-project.com/index.php last;
location ~ /[^/]+/index\.php$ {
include fastcgi_params;
fastcgi_pass unix:/var/run/fcgi.sock;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
}
}
All works fine (except that I wish to prevent to list subdir name in location directive), so I can call http://localhost/www.my-project.com. But when calling http://localhost/www.my-project.com.blabla the location directive from above is called and my internal error page is served. So I tried to change location directive to
location ~ ^/www\.my-project\.com(/|$) {
But that causes any existing file (CSS, JS...) to be rewritten to index.php, which then returns an 404 itself. Why does a change of location causes this horrible behaviour, I can see no logical difference between location /www.my-project.com and location ~ ^/www\.my-project\.com(/|$).
I'd suggest excluding the assets from the rewrite, you can do that by adding a new location, something like this
location /(css|js|images) {
root /var/www/www.my-project.com/web;
try_files $uri =404;
}
And for the location issue, you can match exact locations using =
location = /www.my-project.com {

Resources