DerekE DerekE - 6 months ago 51
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

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!

Comments