Nginx rewrite rule for CodeIgniter - php

Here is the rule in English:
Any HTTP request other than those for index.php, assets folder, files folder and robots.txt is treated as a request for your index.php file.
I have an .htaccess file that works correctly on Apache server:
RewriteCond $1 !^(index\.php|assets|files|robots\.txt)
RewriteRule ^(.*)$ index.php/$1 [L]
Some correct results for this rule:
example.com = example.com/index.php
example.com/index.php/welcome = example.com/welcome
example.com/assets/css/main.css != example.com/index.php/assets/css/main.css
I tried some tools to convert from htaccess rule to nginx rule but all were incorrect.
Via http://winginx.com/htaccess (missing the exception rules for assets folder...):
location / { rewrite ^(.*)$ /index.php/$1 break; }
Via http://www.anilcetin.com/convert-apache-htaccess-to-nginx/ (error in $1 value):
if ($1 !~ "^(index.php|assets|files|robots.txt)"){
set $rule_0 1$rule_0;
}
if ($rule_0 = "1"){
rewrite ^/(.*)$ /index.php/$1 last;
}
How can I fix this? It's really hard to debug the rule.
Here is my nginx config so far:
server {
listen 80;
server_name www.example.com example.com;
location / {
try_files $uri $uri/ /index.php?/$request_uri;
}
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}

You can add this to your config:
location ~* ^/(assets|files|robots\.txt) { }
This will work correctly with your location / rule.
Your config also need to add root document and default index file.
...
root /ftp/wardrobe;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?/$request_uri;
}
location ~* ^/(assets|files|robots\.txt) { }
...

You want to do this instead:
if ($request_uri !~ ^/(index\.php|assets|files|robots\.txt)) {
rewrite ^/(.*)$ /index.php/$1 last;
}
$request_uri is for the original URI request by the client. If you want the URI request AFTER other Nginx rewrite rules have processed it then you would use $uri. However, for what you are trying to do the prior would be the one you would want.
Also, you need to escape special regular expression characters like . by using a backslash.

Please try this. It works for me.
server {
server_name domain.tld;
root /var/www/codeignitor;
index index.html index.php;
# set expiration of assets to MAX for caching
location ~* \.(ico|css|js|gif|jpe?g|png)(\?[0-9]+)?$ {
expires max;
log_not_found off;
}
location / {
# Check if a file or directory index file exists, else route it to index.php.
try_files $uri $uri/ /index.php;
}
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;
}
}

Related

Nginx redirect with/without php extension

I am building an NGINX virtual host that should:
redirect pages ending with .php to the version without extension (301 redirect)
properly handle URLs not ending with .php by passing them to FASTCGI for php execution
My issue is that this will in effect create an infinite redirect loop. What am I missing here?
server {
server_name ~^my\.domain\.com$;
listen 80;
root /path/to/root;
error_page 404 /404.php;
location ~ \.php$ {
rewrite ^(.*)\.php$ $1 permanent;
break;
}
location / {
index index.php;
try_files $uri $uri/ #extensionless-php;
}
location #extensionless-php {
rewrite ^(.*)$ $1.php last;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# rest of fastcgi configuration...
}
}
For a start, you cannot have two location ~ \.php$ blocks. The solution is to process the fastcgi_pass within the named location itself and avoid the internal rewrite to .php. Something like this:
location / {
try_files $uri #php;
}
location #php {
try_files $uri.php $uri/index.php =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_pass ...;
}
location ~* ^(.*)\.php$ {
return 301 $1;
}
Notice that the index directive and the $uri/ elements are no longer required.

Nested Laravel Project Nginx Config

We are introducing a new section on our website which uses the Laravel framework. It is placed in a sub-directory, for example /newsection. How should I configure the nginx.conf without making any conflicts with my previous rewrite rules.
This is my current nginx.conf
server {
listen 80;
server_name localhost www.website.com;
root /home/www/website;
index index.html index.php;
location /newsection/ {
rewrite ^/ /newsection/public/index.php last;
# this is my attempt at it
}
location / {
try_files $uri $uri/ #rewrite;
}
location /php-status {
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $request_filename;
include fastcgi_params;
}
location #rewrite {
rewrite ^/([\w_-]+)/?$ /index.php?page=$1 last;
rewrite ^/([\w_-]+)/([\w_-]+)/?$ /index.php?page=$1&slug=$2 last;
rewrite ^/([\w_-]+)/([\w_-]+)/([\w_-]+)/?$ /index.php?page=$1&slug=$2&pagination=$3 last;
}
include php.conf;
}
If it works like most frameworks I know work, this should work
location /newsection/ {
try_files $uri $uri/ /newsection/public/index.php$request_uri;
}
If this returns 404 try removing the extra /newsection in the fallback URI of the try_files
Try this for laravelin subdirectories
location ^~ /laravel {
alias /var/www/laravel/public;
try_files $uri $uri/ #laravel;
location ~ \.php {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(.*)$;
include /etc/nginx/fastcgi_params;
}
}
location #laravel {
rewrite /laravel/(.*)$ /laravel/index.php?/$1 last;
}

remove .php from url with rewrite rule

I want to rewrite the url in nginx so that the .php extension can be omitted.
This is what I have, but this isn't working for me. Anyone any idea how to do this?
Thanks.
server {
listen 80;
server_name example.com;
return 301 $scheme://www.example.com$request_uri;
}
server {
listen 80;
root /usr/share/nginx/www;
index index.php;
server_name www.example.com;
error_page 404 http://www.example.com/404.php;
autoindex off;
error_log /usr/share/nginx/www/nginx_error.log warn;
location / {
rewrite ^(.*)$ /$1.php;
}
location = / {
rewrite ^ /index.php;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}
}
this is my whole config file.
Spent a while trying to get this to work properly. Both php files and other assets working:
location / {
if (!-e $request_filename){
rewrite ^(.*)$ /$1.php;
}
try_files $uri $uri/ /index.php?$query_string;
}
#Makromat I think the 404 issue you are mentioning in the comments is that your / location is resolving to /.php without a file name, so to solve it we might add another location just to handle this special case
location / {
rewrite ^(.*)$ /$1.php;
}
location = / {
rewrite ^ /index.php;
}
Try this and tell me if it works
EDIT:
Ok scratch that, I have a better idea, the first case will fail if the original URL already contains the .php extension so it's better to define it as a fall back solution, try this
location / {
try_files $uri $uri.php $uri/;
}
Try replace this with your current php block
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/var/run/php5-fpm.sock;
}
Something like this should be what you are looking for.
location ^/(.*)$ {
rewrite ^(.*)$ /$1.php;
}

CodeIgniter, NGINX inside folder not working

I have a stock CI application that runs on NGINX. There is no rewriting (I tried for 16 hours and couldn't not get it to work. It's either 500, 404, 403, or input file not specified), php files are passed to php-fpm.
Here's my default file under available-sites (Ubuntu 12.04, tried everything on CentOS and nothing worked):
server {
listen 80;
root /usr/share/nginx/www/;
index index.php index.html index.htm;
server_name fish-in-a-bowl.net;
location / {
try_files $uri $uri/ /index.html;
}
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/www/cloud;
}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
location ~ \.php$ {
#fastcgi_pass 127.0.0.1:9000;
# With php5-fpm:
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
And config.php:
$config['base_url'] = 'http://fish-in-a-bowl.net/zz/';
$config['index_page'] = 'index.php';
//$config['index_page'] = '';
//$config['uri_protocol'] = 'PATH_INFO';
//$config['uri_protocol'] = 'QUERY_STRING';
//$config['uri_protocol'] = 'REQUEST_URI';
//$config['uri_protocol'] = 'DOCUMENT_URI';
//$config['uri_protocol'] = 'ORIG_PATH_INFO';
$config['uri_protocol'] = 'AUTO';
I've tried all the options available, but none worked. This node is on Digital Ocean, they have tutorials for setting up CI with Apache but not NGINX.
The default controller works, but when accessed via http://fish-in-a-bowl.net/zz/index.php/welcome I get No input file specified.
Help? This is SO strange.
SCREENSHOT >
In your nginx service config change:
location / {
try_files $uri $uri/ /index.html;
}
To
location / {
try_files $uri $uri/ /index.php;
}
In your CI config.php set:
$config['index_page'] = '';
$config['uri_protocol'] = "REQUEST_URI";
try this in your nginx setting
# enforce NO www
if ($host ~* ^www\.(.*))
{
set $host_without_www $1;
rewrite ^/(.*)$ $scheme://$host_without_www/$1 permanent;
}
# canonicalize codeigniter url end points
# if your default controller is something other than "welcome" you should change the following
if ($request_uri ~* ^(/welcome(/index)?|/index(.php)?)/?$)
{
rewrite ^(.*)$ / permanent;
}
# removes trailing "index" from all controllers
if ($request_uri ~* index/?$)
{
rewrite ^/(.*)/index/?$ /$1 permanent;
}
# removes trailing slashes (prevents SEO duplicate content issues)
if (!-d $request_filename)
{
rewrite ^/(.+)/$ /$1 permanent;
}
# removes access to "system" folder, also allows a "System.php" controller
if ($request_uri ~* ^/system)
{
rewrite ^/(.*)$ /index.php?/$1 last;
break;
}
# unless the request is for a valid file (image, js, css, etc.), send to bootstrap
if (!-e $request_filename)
{
rewrite ^/(.*)$ /index.php?/$1 last;
break;
}
Try the following, works a dream for me. Don't forget to change the fastcgi_pass, and backup your current config before you try it.
server
{
listen Server IP:80;
server_name domain.name;
access_log /var/log/nginx/access.log;
root /path/to/www;
index index.php index.html index.htm;
# enforce www (exclude certain subdomains)
# if ($host !~* ^(www|subdomain))
# {
# rewrite ^/(.*)$ $scheme://www.$host/$1 permanent;
# }
# enforce NO www
if ($host ~* ^www\.(.*))
{
set $host_without_www $1;
rewrite ^/(.*)$ $scheme://$host_without_www/$1 permanent;
}
# canonicalize codeigniter url end points
# if your default controller is something other than "welcome" you should change the following
if ($request_uri ~* ^(/welcome(/index)?|/index(.php)?)/?$)
{
rewrite ^(.*)$ / permanent;
}
# removes trailing "index" from all controllers
if ($request_uri ~* index/?$)
{
rewrite ^/(.*)/index/?$ /$1 permanent;
}
# removes trailing slashes (prevents SEO duplicate content issues)
if (!-d $request_filename)
{
rewrite ^/(.+)/$ /$1 permanent;
}
# removes access to "system" folder, also allows a "System.php" controller
if ($request_uri ~* ^/system)
{
rewrite ^/(.*)$ /index.php?/$1 last;
break;
}
# unless the request is for a valid file (image, js, css, etc.), send to bootstrap
if (!-e $request_filename)
{
rewrite ^/(.*)$ /index.php?/$1 last;
break;
}
# catch all
error_page 404 /index.php;
# use fastcgi for all php files
location ~ \.php$
{
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /path/to/www/$fastcgi_script_name;
include fastcgi_params;
}
# deny access to apache .htaccess files
location ~ /\.ht
{
deny all;
}
}
Just add a new location block for CI
location ~ /zz(?<myuri>.*) {
root /path/to/root/zz;
try_files $myuri $myuri/ /index.php$myuri$is_args$query_string;
}
That should do it all, test it and tell me how it goes.
try this
location ~ \.php($|/.+) {
fastcgi_pass 127.0.0.1:9000;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
fastcgi_param SCRIPT_FILENAME $request_filename;
include fastcgi_params;
}
location /atri/ {
alias /var/www/html/atri/;
try_files $uri $uri/ /atri/index.php;
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $request_filename;
}
}

Zend Framework additional Get params with NGINX

I configured my NGINX for Zend in the following way (PHP 5.3 with fpm):
server {
root /home/page/public/;
index index.php index.html index.htm;
server_name localhost;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
}
Now i want to process additional get params like: http://web.site/index?par=1
WIth my local dev system (Apache) it works fine but not under NGINX which did'T deliver the get params.
Anny suggestions?
Edit:
Now i use the following config which seems to work but i'm not happy with it since everybody suggests "use try_files whenever possible".
location / {
if (!-e $request_filename) {
rewrite /(.*)$ /index.php?q=$1 last;
break;
}
}
From Nginx docs ( http://wiki.nginx.org/HttpCoreModule#try_files):
If you need args preserved, you must do so explicitly:
location / {
try_files $uri $uri/ /index.php?$args;
}
I use a rewrite module for this; try replacing your location / block with the following:
location / {
index index.php index.html index.htm;
}
if (!-e $request_filename) {
rewrite ^.*$ /index.php last;
}

Categories