Назад | Перейти на главную страницу

CodeIgniter nginx правила перезаписи URL-адресов i8ln

Я тестирую сайт, созданный с помощью CodeIgniter на ящике Vagrant для разработки (Ubuntu TLS 14 с nginx 1.8.1 и PHP 5.6 с php-fpm), и CodeIgniter, похоже, не работает с nginx.

После нескольких проб и ошибок и сбора кусочков и кусочков из других похожих проблем я смог выполнить частичное перенаправление. Этот сайт имеет структуру URL-адресов, основанную на региональных кодах ISO, например: http://example.com/REGION/language поэтому, если я просматриваю сайт из США, он перенаправляется на http://example.com/US/en и если Европа, чем http://example.com/EU/en. Существует как минимум 4-5 таких комбинаций с использованием базы данных GeoIP и редиректов CodeIgniter 301.

Мой nginx конфигурация выглядит следующим образом:

# Default server configuration
server {

    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/html;

    # Add index.php to the list if you are using PHP
    index index.php index.html index.htm index.nginx-debian.html;

    server_name _;

    location / {

        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ =404;
        #try_files $uri /index.html index.php =404;
        #try_files $uri $uri/ /index.php;
    }

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    location ~ \.php$ {

        # regex to split $uri to $fastcgi_script_name and $fastcgi_path
        fastcgi_split_path_info ^(.+\.php)(/.+)$;

        # Check that the PHP script exists before passing it
        try_files $fastcgi_script_name =404;

        # Bypass the fact that try_files resets $fastcgi_path_info
        # see: http://trac.nginx.org/nginx/ticket/321
        set $path_info $fastcgi_path_info;
        fastcgi_param PATH_INFO $path_info;

        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;

        #FastCGI conf
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param QUERY_STRING $query_string;
        fastcgi_param REQUEST_METHOD $request_method;
        fastcgi_param CONTENT_TYPE $content_type;
        fastcgi_param CONTENT_LENGTH $content_length;

        fastcgi_param SCRIPT_NAME $fastcgi_script_name;
        fastcgi_param REQUEST_URI $request_uri;
        fastcgi_param DOCUMENT_URI $document_uri;
        fastcgi_param DOCUMENT_ROOT $document_root;
        fastcgi_param SERVER_PROTOCOL $server_protocol;
        fastcgi_param HTTPS $https if_not_empty;

        fastcgi_param GATEWAY_INTERFACE CGI/1.1;
        fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;

        fastcgi_param REMOTE_ADDR $remote_addr;
        fastcgi_param REMOTE_PORT $remote_port;
        fastcgi_param SERVER_ADDR $server_addr;
        fastcgi_param SERVER_PORT $server_port;
        fastcgi_param SERVER_NAME $server_name;

        # PHP only, required if PHP was built with --enable-force-cgi-redirect
        fastcgi_param REDIRECT_STATUS 200;
    }

    # deny access to .htaccess files, if Apache's document root concurs with nginx's one
    location ~ /\.ht {
        deny all;
    }

    location /exmple {

        root /var/www/html/;
        index index.php;

        location ~ ^/example/(.+\.php)$ {

            client_max_body_size 4M;
            client_body_buffer_size 128k;
            root /var/www/html/;
            try_files $uri =404;
            fastcgi_split_path_info ^(.+\.php)(.*)$;

            # With php5-fpm:
            fastcgi_pass unix:/var/run/php5-fpm.sock;
            fastcgi_index index.php;
            include /etc/nginx/fastcgi_params;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        }

        location ~* ^/example/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt)) {

            root /var/www/html/;
        }

        # CI rewrite rules
        if ($host ~* ^www\.(.*)) {

            set $host_without_www $1;
            rewrite ^/(.*)$ $scheme://$host_without_www/$1 permanent;
        }

        # Canonicalize codeigniter url end points and if your default controller is something other than "welcome" you should change the following
        if ($request_uri ~* ^(/pages(/view)?|/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;
    }

}

Поэтому, когда я просматриваю его с локального хоста, например http://192.168.33.15/example/ он перенаправляет на http://192.168.33.15/example/INT/en который используется по умолчанию, если действительное местоположение не найдено в базе данных GeoIP, где example это подкаталог внутри nginx корень. Здесь ошибок нет, но nginx не перенаправляет должным образом и интерпретирует INT/en как папку, чтобы она выскакивала с 404 Not Found ошибка.

Я просмотрел много сообщений на форуме Serverfault, Stackexchange и другие онлайн-ресурсы, но ни один из них не помог, и поскольку документации по CodeIgniter или nginx сайты либо это кажется подходящим местом, чтобы спросить.

Нашел гораздо более простое решение. После чего CodeIgniter делает "за кулисами" для чистых URL-адресов; в Apache эта перезапись работает, отправляя каждый запрос как http://example.com/index.php?/controller/method который затем обрабатывается CodeIgniter Так что ваши config.php должен выглядеть

$config['base_url'] = 'http://example.com'
$config['index_page'] = '';
$config['uri_protocol'] = 'REQUEST_URI';

Чтобы добиться того же в nginx вам придется переписывать каждый запрос идентичным образом. Точно настроил мой nginx конфигурация с:

location /example {

    root /var/www/html/;
    index index.php;

    location ~ ^/example/(.+\.php)$ {

        fastcgi_buffer_size 128k;
        fastcgi_buffers 256 4k;
        fastcgi_busy_buffers_size 256k;
        fastcgi_temp_file_write_size 256k;
        root /var/www/html/;
        include /etc/nginx/snippets/fastcgi-php.conf;
    }

    location ~* ^/example/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt)) {
        root /var/www/html/;
    }

    # Enforce SSL
    if ($scheme = http) {
        return 301 https://$host$request_uri;
    }

    # CI rewrite rules
    if ($host ~* ^www\.(.*)) {
        set $host_without_www $1;
        rewrite ^/(.*)$ $scheme://$host_without_www/$1 permanent;
    }

    if ($request_uri ~* ^(/example/(US|EU|INT)/(en|de)(.*))?$) {
        rewrite ^/(.*)$ /example/index.php?/$1 last;
    }

    if ($request_uri ~* ^(/example/(US|EU|INT)/(en|de)/(.*))?$) {
        rewrite ^/(.*)$ /example/index.php?/$1 last;
    }

    # catch all
    error_page 404 /index.php;
}

Недостающее звено существовало в nginx переписать журнал отладки поэтому, если вы хотите знать о своих правилах перезаписи и соответствуют ли они вашему набору правил, добавьте это в свой nginx конфигурация:

server{
  ...
  rewrite_log on;
  error_log /var/log/nginx/error.log info;
  ...
}

И nginx предоставит вам журнал каждого запроса с совпадением или без совпадения с вашим регулярным выражением PCRE. Отсюда вы можете настроить свою конфигурацию. Мне пришлось добавить путь (каталог) example в nginx файл конфигурации, чтобы правила перезаписи работали должным образом.