DerekE DerekE - 2 years ago 283
PHP Question

Proper way to configure NGINX with rewrite and valid mime types

I'm attempting to test out NGINX and potentially make a switch from Apache. Which I've read nginx is much faster, but I want to be the judge of that. I'm having issues getting the configuration of NGINX to match that of my Apache setup -- mainly rewrite rules. I'll explain how my applications works and what I want to be able to do in NGINX.

Currently I have my application handling all the REQUEST_URI's sent to the server. Even if the URI doesn't exist, my application handles processing of that URI. I'm able to do this because of a rewrite rule for Apache.

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?_url=$1 [QSA,NC]
</IfModule>


As you can see if the file or directory doesn't actually exist, it gets sent to index.php. I don't even check for the query string, I just handle the processing of the URI itself via the PHP variable $_SERVER['REQUEST_URI'] which is setup inside NGINX as fastcgi_param REQUEST_URI $request_uri;. I want to accomplish this exact thing with NGINX, but I've been only kind of successful with that.

So basically, if domain.com/register.php exists, then it is going to go to that url, if not it is going to be redirected to domain.com/index.php and the application handles the URI from there.

Here is my config file for my server. This is included at the bottom of nginx.conf file

server {
listen ####:80;
server_name ####;

charset utf-8;

access_log /var/www/#####/logs/access-nginx.log;
error_log /var/www/#####/logs/error-nginx.log;

root /var/www/######/public/;

location / {
index index.php index.html;
include /etc/nginx/mime.types;
try_files $uri /index.php?_url=$1;

include /etc/nginx/fastcgi.conf;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
fastcgi_pass unix:/var/run/php-fpm.socket;

autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
rewrite_log on;
}
}


So this kind of works. What I mean by that is the try_files $uri /index.php?_url=$1 directive is processing the URI the way I want it to, but MIME types don't seem to work. Everything is being processed as text/html. Which means that my .css and .js files have to be turned into a .php file and a header attached in order for it to be processed correctly. image and font files seem to function correctly, but Chrome still shows the mime type as html. I have the mime.types file being included, so I can't figure out why it's doing that. I did try to use a "rewrite" directive to handle the what try_files is doing, but that didn't work.

This is the rewrite I tried inside the location / block:

if (!-e $request_filename){
rewrite ^(.*)$ /index.php?_url=$1;
}


So my question is this: How do I properly rewrite my uri for non-existent files and directories while serving the proper mime type for the files automatically?

Answer Source

I ended up solving my own issue. What I had to do here was to process PHP files on their own and it took for a while to figure out that for sure. Here is the final .conf file that sends the correct mime types and also rewrites the way I needed it. Hopefully this helps someone else as well.

server {
    listen #######:80;
    server_name ######;

    charset utf-8;

    access_log /var/www/######/logs/access-nginx.log;
    error_log /var/www/#######/logs/error-nginx.log;

    root /var/www/#########/public/;

    location ~ \.php$ {
        include /etc/nginx/mime.types;
        try_files $uri /index.php?_url=$1;
        include /etc/nginx/fastcgi.conf;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_index  index.php;
        fastcgi_pass unix:/var/run/php-fpm.socket;

    }

    location / {
        index index.php index.html;
        include /etc/nginx/mime.types;
        try_files $uri /index.php?_url=$1;

        autoindex on;
        autoindex_exact_size off;
        autoindex_localtime on;
        rewrite_log on;
    }
}

Using the location ~ .php$ section made it so that only PHP files were being sent to php-fpm. I also use the try_files directive to handle sending all the URI's that don't exist to my script, which is what my application expects. Hopefully this helps someone else out there!

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download