Search code examples
url-rewritingnginxfastcgiphp

nginx not passing off rewrites to php


Here are the pertinent lines of my nginx.conf file.

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

location @rewrite {
    rewrite ^/customer/(.*)$ /customersDisplay.php?id=$1;
    rewrite ^/attc2/(.*)$ /usr/www/vault/$1;
    rewrite ^/xport/(.*)$ /usr/www/files/innoMatrix/xport/$1;
    rewrite ^/forms/(.*)$ /usr/www/files/innoMatrix/forms/$1;
    rewrite ^/grafx/(.*)$ /usr/www/files/innoMatrix/grafx/$1;
}

location ~ \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass unix:/var/run/php-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    fastcgi_param DATABASE innoMatrix;
    include fastcgi_params;
}

Can anyone right off had see why customer wouldnt be handed off to the fpm socket? It redirects properly, but downloads the file instead of interpreting it in PHP. I use a nearly identical config for my phalcon based app and it works a champ.


Solution

  • I strongly recommend learning how to debug nginx rewrites by turning on rewrite_log on. If you did that you'd almost certainly see that what is happening is that:

    1. Request to '/customer/foo' comes in.
    2. It doesn't match a file in the first location block, so gets tried through the @rewrite block.
    3. The @rewrite block rewrites the request to /customersDisplay.php?id=foo and restarts the processing the request.
    4. The first location block now tries the file /customersDisplay.php and it exists, so it gets served as the file.

    Putting it as gently as I can, the way you've written your nginx conf is 'against common practice for nginx', aka don't do it like that.

    You presumably are migrating from, or have used Apache rewrite in the past, and are using the same style of rewrites in Nginx. You almost certainly don't need to use the for mapping requests to PHP.

    I suggest, first just copying the file fastcgi_params to fastcgi_php_params and including the other proxy settings in there, (to avoid duplication) and then modifying your nginx config to look something like:

    #Mapping external URL to internal file path
    rewrite ^/attc2/(.*)$ /usr/www/vault/$1;
    rewrite ^/xport/(.*)$ /usr/www/files/innoMatrix/xport/$1;
    rewrite ^/forms/(.*)$ /usr/www/files/innoMatrix/forms/$1;
    rewrite ^/grafx/(.*)$ /usr/www/files/innoMatrix/grafx/$1;
    
    #All requests below 'customer' are fed to PHP
    location ~ /customer/(.*)$ {
        try_files $uri $uri/ /customersDisplay.php?id=$1 =404;
        include fastcgi_php_params;
    }
    
    #Try and serve all other static files directly, if they exist.
    location ~* ^[^\?\&]+\.(html|jpg|jpeg|gif|png|ico|css|zip|tgz|gz|rar|bz2|doc|xls|pdf|ppt|txt|tar|mid|midi|wav|bmp|rtf|js|svg|woff|ttf)$ {
        try_files $uri /index.php?file=$1;
    
        #access_log off;
        expires 24h;
        add_header Pragma public;
        add_header Cache-Control "public, must-revalidate, proxy-revalidate";
    }
    
    #final catch all location, pass all remaining requests to PHP.
    location / {
        try_files $uri $uri/ /index.php =404;
        include fastcgi_php_params;
    }