Rewrite all requests to index.php with nginx
Asked Answered
S

9

79

In my apache configuration I have the following simple rewrite rule which

  1. unless file exists will rewrite to index.php
  2. on the urls you never see the file extension (.php)

how can I rewrite this in nginx?

#
# Redirect all to index.php
#
RewriteEngine On

# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteCond %{REQUEST_URI} (/[^.]*|\.)$ [NC]
RewriteRule .* index.php [L]

Here's how my nginx server block looks like now, but it doesn't work :(

root /home/user/www;
index index.php;

# Make site accessible from http://localhost/
server_name some-domain.dev;


###############################################################
# exclude /favicon.ico from logs
location = /favicon.ico {
    log_not_found off;
    access_log off;
}   

##############################################################
# Disable logging for robots.txt
location = /robots.txt {
    allow all;
    log_not_found off;
    access_log off;
}   

##############################################################
# Deny all attempts to access hidden files such as 
# .htaccess, .htpasswd, .DS_Store (Mac).
location ~ /\. {
    deny all;
    access_log off;
    log_not_found off;
}   

##############################################################
#   
location / { 
    include /etc/nginx/fastcgi_params;
    fastcgi_param   SCRIPT_FILENAME  $document_root/index.php$args;
    fastcgi_pass    127.0.0.1:9000;
}   

###############################################################
# serve static files directly
location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico)$ {
    access_log off;
    expires    30d;
}   

###############################################################
# redirect server error pages to the static page /50x.html
error_page   500 502 503 504  /50x.html;
location = /50x.html {
    root html;
}   

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#   
location ~ \.php$ {
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    # NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
    # With php5-cgi alone:
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    include fastcgi_params;
}
Superpower answered 16/10, 2012 at 23:17 Comment(0)
L
42

1 unless file exists will rewrite to index.php

Add the following to your location ~ \.php$

try_files = $uri @missing;

this will first try to serve the file and if it's not found it will move to the @missing part. so also add the following to your config (outside the location block), this will redirect to your index page

location @missing {
    rewrite ^ $scheme://$host/index.php permanent;
}

2 on the urls you never see the file extension (.php)

to remove the php extension read the following: http://www.nullis.net/weblog/2011/05/nginx-rewrite-remove-file-extension/

and the example configuration from the link:

location / {
    set $page_to_view "/index.php";
    try_files $uri $uri/ @rewrites;
    root   /var/www/site;
    index  index.php index.html index.htm;
}

location ~ \.php$ {
    include /etc/nginx/fastcgi_params;
    fastcgi_pass  127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /var/www/site$page_to_view;
}

# rewrites
location @rewrites {
    if ($uri ~* ^/([a-z]+)$) {
        set $page_to_view "/$1.php";
        rewrite ^/([a-z]+)$ /$1.php last;
    }
}
Lynnalynne answered 17/10, 2012 at 9:25 Comment(6)
Unfortunately it didn't really work. I get an empty response from nginx. In error log it reports the following 2012/10/17 15:23:14 [alert] 17437#0: worker process 17440 exited on signal 11 (core dumped)Superpower
the combination of the two configs probably messes things up when you combine them like this, do they work when you only try one at a time?Lynnalynne
can u tell me the configuration for nested levels also. this configuration works well on first level routesImplantation
This method is less versatile than the higher rated answers here. Particularly you'll get into problems using this method behind a reverse proxy where the url will be rewritten to the local hostname and not the public one.Parrotfish
What does = do in try_files = line? and what does ^ do in rewrite ^ line?Coaming
$scheme://$host/ will remove the port from url which is not desiredCoaming
L
146

I have tried this and succeeded to get my index page. When I have added this code in my site configuration file:

location / {
    try_files $uri $uri/ /index.php;
}

Inside the configuration file itself it is explained that these are the configured steps

First attempt to serve request as file, then as directory, then fall back to index.html

In my case it is index.php, as I am providing page through php code.

Lewison answered 23/4, 2013 at 13:53 Comment(7)
Wow, that is way too easy.Warga
This works but get variables aren't passed correctly anymore. Any ideas on how to do that?Custom
@Custom I believe this will do the trick: try_files $uri $uri/ /index.php?$args;Probationer
You're my hero!Bowes
@Custom try: try_files $uri $uri/ /index.php$is_args$args;Allophane
@Custom it just works for most urls, not all. if you go to the url /r9eijguhnbhher.php (or ANYTHING that ends with .php ) it doesn't work. this works for all urls that does not end with .phpGradatim
Warning: this only works for urls that does not end with .php , for example it doesn't work with /example.php , example.php here will NOT be redirected to index.phpGradatim
I
67

To pass get variables as well use $args:

location / {
    try_files $uri $uri/ /index.php?$args;
}
Interrogate answered 12/2, 2014 at 15:15 Comment(1)
Warning: this only works for urls that does not end with .php , for example it doesn't work with /example.php , example.php will NOT be redirected to index.phpGradatim
L
42

1 unless file exists will rewrite to index.php

Add the following to your location ~ \.php$

try_files = $uri @missing;

this will first try to serve the file and if it's not found it will move to the @missing part. so also add the following to your config (outside the location block), this will redirect to your index page

location @missing {
    rewrite ^ $scheme://$host/index.php permanent;
}

2 on the urls you never see the file extension (.php)

to remove the php extension read the following: http://www.nullis.net/weblog/2011/05/nginx-rewrite-remove-file-extension/

and the example configuration from the link:

location / {
    set $page_to_view "/index.php";
    try_files $uri $uri/ @rewrites;
    root   /var/www/site;
    index  index.php index.html index.htm;
}

location ~ \.php$ {
    include /etc/nginx/fastcgi_params;
    fastcgi_pass  127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /var/www/site$page_to_view;
}

# rewrites
location @rewrites {
    if ($uri ~* ^/([a-z]+)$) {
        set $page_to_view "/$1.php";
        rewrite ^/([a-z]+)$ /$1.php last;
    }
}
Lynnalynne answered 17/10, 2012 at 9:25 Comment(6)
Unfortunately it didn't really work. I get an empty response from nginx. In error log it reports the following 2012/10/17 15:23:14 [alert] 17437#0: worker process 17440 exited on signal 11 (core dumped)Superpower
the combination of the two configs probably messes things up when you combine them like this, do they work when you only try one at a time?Lynnalynne
can u tell me the configuration for nested levels also. this configuration works well on first level routesImplantation
This method is less versatile than the higher rated answers here. Particularly you'll get into problems using this method behind a reverse proxy where the url will be rewritten to the local hostname and not the public one.Parrotfish
What does = do in try_files = line? and what does ^ do in rewrite ^ line?Coaming
$scheme://$host/ will remove the port from url which is not desiredCoaming
P
19

Flat and simple config without rewrite, can work in some cases:

location / {
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME /home/webuser/site/index.php;
}
Pollen answered 6/6, 2013 at 11:41 Comment(4)
Good one! Just what I looking for, works for me and I think that it's an optimum solution, faster than rewriting.Quyenr
@Quyenr I agree, this is a better solution. If it needed anything else at all it would be worth the effort on overhead. iutinvg, +1 for fast static route.Extend
The Nginx documentation advises against proxying all calls to PHP: wiki.nginx.org/Pitfalls#Proxy_EverythingSusa
NGINX advises against only in the case that you have static content to serve as well. If this is not your case, I believe this is the best solution.Brancusi
Y
11

Using nginx $is_args instead of ? For GET query Strings

location / { try_files $uri $uri/ /index.php$is_args$args; }
Yonder answered 23/11, 2016 at 18:11 Comment(1)
**Warning: this only works for urls that does not end with .php , for example it doesn't work with /example.php , example.php here will NOT be redirected to index.php **Gradatim
A
5

Here's the answer of your 2nd question :

   location / {
        rewrite ^/(.*)$ /$1.php last;
}

it's work for me (based my experience), means that all of your blabla.php will rewrite into blabla

like http://yourwebsite.com/index.php to http://yourwebsite.com/index

Alginate answered 20/4, 2016 at 14:16 Comment(0)
A
1

Here is what worked for me to solve part 1 of this question:

    location / {
            rewrite ^([^.]*[^/])$ $1/ permanent;
            try_files $uri $uri/ /index.php =404;
            include fastcgi_params;
            fastcgi_pass php5-fpm-sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
            fastcgi_intercept_errors on;
    }

rewrite ^([^.]*[^/])$ $1/ permanent; rewrites non-file addresses (addresses without file extensions) to have a "/" at the end. I did this because I was running into "Access denied." message when I tried to access the folder without it.

try_files $uri $uri/ /index.php =404; is borrowed from SanjuD's answer, but with an extra 404 reroute if the location still isn't found.

fastcgi_index index.php; was the final piece of the puzzle that I was missing. The folder didn't reroute to the index.php without this line.

Accouplement answered 12/11, 2013 at 21:12 Comment(0)
E
0

If you want to pass just the index.php ( no other php file will be passed to fastcgi ) to fastcgi in case you have routes like this in a framework like codeigniter

$route["/download.php"] = "controller/method";


location ~ index\.php$ {
        fastcgi_pass 127.0.0.1:9000;
        include fastcgi.conf;
}
Edition answered 12/2, 2015 at 19:18 Comment(0)
N
0
index index.php;
location / { try_files  $uri $uri/ =404; }
error_page 404 /?URL=$uri;
Neologize answered 23/5, 2024 at 2:33 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.