Я тестирую сайт, созданный с помощью 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 файл конфигурации, чтобы правила перезаписи работали должным образом.