Замена RewriteRule в nginx

Итак, имеем веб сервер Nginx в качестве фронтэнда, на бакэндах Apache и какой-нибудь fastcgi (spawn-fcgi или php-fpm). Функциональные возможности серверов, nginx и apache, несколько различаются, и одно из различий как раз в том, что nginx не поддерживает обработку файлов htaccess, которые в apache используются практически повсеместно. Большинство сайтовых движков (CMS), поддерживают возможность генерировать так называемые ЧПУ(человекопонятный урл, в оригинале, SEF - search engines friendly url), но для этого, веб сервер, должен обрабатывать строку запроса определенным образом, что apache и делает с помощью mod_rewrite и правил в файле .htaccess. Задача: заменить правила .htaccess, соответствующими директивами в конфигурационном файле nginx.conf. Приведу несколько вариантов, для распространенных движков. Все приведенные ниже варианты, рабочие, настроены и проверены на сервере под управлением операционной системы FrereBSD 7.1, версия Nginx 7.59.
Данные настройки касаются стандартных SEF модулей, встроенных в движки. во всех примерах подразумевается, что версия nginx поддерживает именованные location и директиву try_files

Конфигурация Nginx и Apache для Joomla 1.0.15

Правила htaccess:

[apache] RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d ## RewriteCond %{REQUEST_URI} ^(/component/option,com) [NC,OR] ## опционально ## RewriteCond %{REQUEST_URI} (/|\.htm|\.php|\.html|/[^.]*)$ [NC] RewriteRule ^(content/|component/) index.php [/apache]

Эквивалент для настройки сервера nginx

[apache] location / { index index.php index.html index.htm; } ## в поставляемом с дистрибутивом, файле htaccess, есть опциональная строка, по-умолчанию закомментирована ## данный блок ее эквивалент для nginx # # location ^~ /component/option,com { # index index.php index.html index.htm; # try_files $uri $uri/ @joomla; # } ##### location ~* (\.html?|/|/[^.]*)$ { try_files $uri $uri/ @joomla; index index.php index.html index.htm; } location ~ \.php$ { try_files $uri @joomla; fastcgi_pass unix:/tmp/php-fpm.sock; ## Ваш fastcgi сервер fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; ## стандартный файл, идущий с nginx } location @joomla { fastcgi_pass unix:/tmp/php-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root/index.php; include fastcgi_params; } [/apache]

Конфигурация Nginx и Apache для Joomla 1.5.10

Правила htaccess:

[apache] RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_URI} !^/index.php RewriteCond %{REQUEST_URI} (/|\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$ [NC] RewriteRule (.*) index.php RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L] [/apache]

Эквивалент для настройки сервера nginx

[apache] location / { index index.php index.html index.htm; } location ~* (/|\.html?|\.feed|\.pdf|\.raw|/[^.]*)$ { try_files $uri $uri/ @joomla; } location ~ \.php$ { try_files $uri @joomla; fastcgi_pass unix:/tmp/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location @joomla { fastcgi_pass unix:/tmp/php-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root/index.php; 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 REDIRECT_STATUS 200; fastcgi_param SCRIPT_NAME /index.php; 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 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; } [/apache] Примечание: в первом примере, fastcgi_param были загружены из стандартного файла, идущего в поставке nginx, во втором, я не стал инклудить файл с параметрами а просто прописал их в конфиг, обратите внимание что параметр SCRIPT_NAME, отличается от первого примера.

Конфигурация Nginx и Apache для Wordpress 2.7.1

Правила htaccess:

[apache] RewriteBase / RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule . /index.php [L] [/apache]

Эквивалент для веб сервера nginx

[apache] location / { try_files $uri $uri/ @wordpress; index index.php index.html index.htm; } location ~ \.php$ { try_files $uri @wordpress; fastcgi_pass unix:/tmp/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location @wordpress { fastcgi_pass unix:/tmp/php-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root/index.php; include fastcgi_params; } [/apache] Как видите, тут мы тоже просто инклудим стандартный файл с fastcgi параметрами

Конфигурация Nginx и Apache для Drupal 6.12

Правила htaccess:

[apache] RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_URI} !=/favicon.ico RewriteRule ^(.*)$ index.php?q=$1 [L,QSA] [/apache]

Эквивалент для сервера nginx

[apache] location / { try_files $uri $uri/ @drupal; index index.php index.html index.htm; } location ~ \.php$ { try_files $uri @drupal; fastcgi_pass unix:/tmp/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location @drupal { fastcgi_pass unix:/tmp/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root/index.php; --------------------------------------------------------------------------------------------------------------------- fastcgi_param QUERY_STRING q=$uri&$args; fastcgi_param REQUEST_METHOD $request_method; fastcgi_param CONTENT_TYPE $content_type; fastcgi_param CONTENT_LENGTH $content_length; fastcgi_param REDIRECT_STATUS 200; fastcgi_param SCRIPT_NAME /index.php; 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 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; --------------------------------------------------------------------------------------------------------------------- Весь список fastcgi параметров приведен для наглядности, данный блок можно сократить до: include fastcgi_params; fastcgi_param QUERY_STRING q=$uri&$args; fastcgi_param SCRIPT_NAME /index.php; } [/apache] Более короткий и красивый вариант. [apache] location / { try_files $uri $uri/ /index.php?q=$uri&$args; index index.php index.html index.htm; } location ~ \.php$ { fastcgi_pass unix:/tmp/php-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } [/apache] Вот собственно и все, единственное что стоит добавить, все рассмотренные правила касаются именно SEF, я здесь не затрагивал правила безопасности, так-же добавляемые в htaccess почти всеми движками, возможно распишу попозже) Всем удачи.

Комментарии

I tried with your wordpress tutorial. But it''s not working with WordPress MU.
You need somethink like
if (!-e $request_filename) {
rewrite ^.+/?(/wp-.*) $1 last;
rewrite ^.+/?(/.*\\.php)$ $1 last;
rewrite ^(.+)$ /index.php?q=$1 last;
}
to get it works,

it's strange.. I just checked, that the construction works without reproach:
server {
listen ip_addr:80;
server_name wordpressmu;
access_log logs/wordpressmu_access.log;
error_log logs/wordpressmu_error.log;
root /usr/home/wordpressmu/public_html;
location / {
try_files $uri $uri/ @wordpressmu;
index index.php index.html index.htm;
}
location ~ \.php$ {
try_files $uri @wordpressmu;
fastcgi_pass unix:/tmp/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params; #standart
}
location @wordpressmu {
fastcgi_pass unix:/tmp/php-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
include fastcgi_params; #standart
}
Permalink settings: "Day and name", "Month and name" and "Numeric"..

if add this location directive, all work )
location ~* ^/files/.+$ {
rewrite ^/files(/.*)$ /wp-content/blogs.php?file=$1 last;
}

Здесь как бы возникает нубский вопрос - что править? Файл nginx.conf или что-то еще?
Заранее спасибо.

в смысле "что править" ? куда добавлять секцию
location ~* ^/files/.+$ {
rewrite ^/files(/.*)$ /wp-content/blogs.php?file=$1 last;
?
в текущий блок server, в котором описан данный хост.
Это может быть как основной nginx.conf, так и любой другой конфиг, например vhost_wpmu.conf, загруженный в основной файл инклудом.
include /usr/local/etc/nginx/conf/vhost_wpmu.conf; в котором описан данный вхост.
или я не правильно понял вопрос ?

Большое спасибо, Сергей.Буду пробовать править.А Вы сами администрированием чужих серверов на возмездной основе не занимаетесь?

занимаюсь, можете связаться со мной через раздел "контакты", данного сайта)

Господа!
Вот появилась joomla 1.6.
в .htaccess среди правил в секции SEF у неё новая строка появилась: RewriteCond %{REQUEST_URI} (/component/) [OR]
Т.е. теперь эта секция выглядит вот так:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{REQUEST_URI} (/component/) [OR]
RewriteCond %{REQUEST_URI} (/|\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$ [NC]
RewriteRule (.*) index.php
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]

Как теперь по новому нужно правила для NGINX прописать? Что в уже написанное выше добавить?
А то при включенной в админке функции SEF в joomla при навигации по статьям постоянна вылетает ошибка: 404 component not found.
Блин, сделал бы сам, но одно лишь знание синтаксиса регулярных выражений не спасает. Не знаю, как это всё в NGINX и joomla вообще устроено и как работает?

а что за флаг такой [OR] ?

Проверил на демо-данных, косяков вроде не заметил

location / {
    index  index.php index.html index.htm;
}

location ~* (/|\.html?|\.feed|\.pdf|\.raw|/[^.]*)$ {
    try_files $uri $uri/ /index.php;
}

location ~ \.php$ {
    try_files $uri /index.php;
    fastcgi_pass   unix:/tmp/fastcgi.sock;
    fastcgi_index  index.php;
    fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    include        fastcgi_params;
}

Не, так не работает.
Есть ссылка на материал: http://www.skysoftlab.ru/13-cat-2/14-cat-3/4-test-2.html
При переходе по ней ошибка 404 - Component not found
Ссылка сформирована использованием пункта главного меню с типом Материалы категории в формате блога.
Т.е. отображаются материалы из указанной категории на главной странице в виде блога.
У каждого материала и у вложенных в эту категорию других категорий заголовок является ссылкой.
Т.е. ссылаются в данном случае сами на себя. При нажатии на такую ссылку (указана выше) и выскакивает ошибка.
Если SEF в админке отключить, ошибок нет.
При отключенном SEF выше упомянутая ссылка выглядит вот так:
http://skysoftlab.ru/index.php?option=com_content&view=article&id=4:test-2&catid=14&Itemid=101
(com_content - это и есть компонент для отображения контента).

Меня смущает именно новая строка в .htaccess
RewriteCond %{REQUEST_URI} (/component/) [OR]
Там как раз какое-то правило для компонентов. В ошибке и говорится, что компонент не найден.

странно
у меня, с вышеприведенными настройками, ссылка:
http://joomla.grt/index.php?option=com_content&view=article&id=8:beginners&catid=19&Itemid=260
с включенными пунктами:
# Search Engine Friendly URLs
# Use Apache mod_rewrite
# Adds Suffix to URL
отображанется как:
http://joomla.grt/using-joomla/extensions/components/content-component/article-category-list/14-sample-data-articles/19-joomla/8-beginners.html
без каких либо ошибок

А можно взглянуть, что у Вас в fastcgi_params ?

они стандартные, а сам конфиг я уже приводил, то есть кроме этого ничего и нет

root /path/to/public_html;

location / {
index index.php index.html index.htm;
}

location ~* (/|\.html?|\.feed|\.pdf|\.raw|/[^.]*)$ {
try_files $uri $uri/ /index.php;
}

location ~ \.php$ {
try_files $uri /index.php;
fastcgi_pass unix:/tmp/fastcgi.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

Sergey, поясните, пожалуйста, в правилах Nginx для Drupal 6.12 в чём ЛОГИЧЕСКАЯ разница между Вашими записями с именованным location @drupal и более коротким и красивым вариантом?
Пытаюсь разобраться, как это всё должно работать, но совершенно не понятно, почему Вы в более коротком варианте выкинули кучу параметров fastcgi в location ~ \.php$ и вообще перестали проверять наличие файла директивой try_files $uri.
И в догонку... В варианте, где есть location @drupal Вы весь список fastcgi параметров сокращаете до:
include fastcgi_params;
fastcgi_param QUERY_STRING q=$uri&$args;
fastcgi_param SCRIPT_NAME /index.php;
В стандартном файле fastcgi_params эти два параметра - QUERY_STRING и SCRIPT_NAME имеют другое значение.
Они что, таким образом переопределяются сразу после включения файла?
Будьте добры, прокомментируйте.

Статья довольно давно писалась, то есть как 100% рецепт ее воспринимать не стоит, скорее как каркас рабочего конфига)

В варианте, где есть location @drupal Вы весь список fastcgi параметров сокращаете до...
Они что, таким образом переопределяются сразу после включения файла?

да, параметры просто переопределяются

вообще перестали проверять наличие файла директивой try_files

в коротком варианте, в location \.php$ запрос приходит уже в сформированном виде /index.php?q=$uri&$args, в длинном, он формируется в @drupal, с помощью fastcgi параметров
вообще, если не ошибаюсь, Drupal 6.19 на таком конфиге +clean urls, работать не будет ( или будет но не полноценно ), там со слэшем какая-то заморочка
если интересно, могу выложить рабочий конфиг этого сайта

Благодарю. Да, было бы интересно, выложите, пожалуйста.
А я выложу свой. Как раз на Drupal 6.19 с включенными clean urls.
Сделал пока лишь одну тестовую статью, помести её на главную страницу. Вроде всё работает.
Ссылка на неё вот такая: http://www.my_site.ru/test
Без синонима (алиаса) test вот такая: http://www.my_site.ru/node/1
Только пока не понял, как сделать, чтобы к синониму добавлялся суффикс (как в joomla), т.е. чтобы ссылка выглядела, как страничка html и имела вид http://www.my_site.ru/test.html
А в остальном пока проблем с данным конфигом пока что не испытывал.

server {
server_name www.example.com;
root /var/www/sites/example.com;

access_log /var/log/nginx/example.access.log;
error_log /var/log/nginx/example.error.log;

if ($host !~* ^(www.example.com)$ ) {
return 444;
}

location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
index index.php index.html;
}

location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm/default.socket;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

location ~* \.(gif|jpg|jpeg|png|css|pdf|ico)$ {
if ($http_referer !~ ^(http://www.example.com) ) {
return 444;
}
expires max;
}

location ~ /\. {
deny all;
}

location ~* (cron\.php|settings\.php)$ {
deny all;
}
location ~* \.(engine|inc|info|install|module|profile|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)$ {
deny all;
}

location ~* ^(code-style\.pl|Entries.*|Repository|Root|Tag|Template)$ {
deny all;
}
}

server {
server_name example.com;
rewrite ^ $scheme://www.example.com$request_uri permanent;
}

Насчет суффикса, если честно, даже не задумывался :)
Конфиг выглядит примерно так:

server {
listen 80;
server_name www.site.ru;
rewrite ^ http://site.ru$request_uri? permanent;
}

server {
listen 80;
server_name site.ru;

root /home/path/to/public_html;

location ~* \.html$ {}

location / {
rewrite ^/(.*)$ /index.php?q=$1 last;
}

location = /index.php {
if ($request_uri = /index.php) {
rewrite ^ http://$host? permanent;
}
fastcgi_pass unix:/tmp/fastcgi.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

location ~* ^.+\.(jpg|jpeg|gif|png|ico)$ {
access_log off;
expires 30d;
add_header Cache-Control public;
}

location ~* ^.+\.(css|js)$ {
gzip_static on;
access_log off;
expires 30d;
add_header Cache-Control public;
}

location = /favicon.ico {
try_files /favicon.ico =204;
}

location = /robots.txt {
access_log off;
}

location ~* \.(engine|inc|info|install|module|profile|po|sh|.*sql|theme|tpl(\.php)?|xtmpl)$ {
return 404;
}

location ~* ^(code-style\.pl|Entries.*|Repository|Root|Tag|Template)$ {
return 404;
}

location ~* ^.*/files/.+\.(zip|rar|7z|pdf)$ {}

location ~ /files/imagecache/ {
access_log off;
expires 30d;
try_files $uri @drupal;
}

location @drupal {
rewrite ^/(.*)$ /index.php?q=$1 last;
}

location ~ /\.ht {
deny all;
}

Только location ~* (cron\.php|settings\.php)$ надо поднять выше, чем location ~ \.php$

Господа! Измучился уже! Помогитя!

Поставил joomla 1.6 beta 12. Не пускает в админку по адресу http://www.example.com/administrator/
В логе пишет это:

[error] 16292#0: *349 directory index of "/var/www/sites/example.com/administrator/" is forbidden, cl
ient: XXX.XXX.XXX.XXX, server: www.example.com, request: "GET /administrator/ HTTP/1.1", host: "www.example.com"

Правила вот эти (взял с этого блога):

root /path/to/public_html;

location / {
index index.php index.html index.htm;
}

location ~* (/|\.html?|\.feed|\.pdf|\.raw|/[^.]*)$ {
try_files $uri $uri/ /index.php;
}

location ~ \.php$ {
try_files $uri /index.php;
fastcgi_pass unix:/tmp/fastcgi.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

пустит через:
http://www.example.com/administrator/index.php
с ходу не соображу как там локейшн прописывать в конфе, будет время гляну

После location / {...} добавить вот это:

location /administrator/ {
index index.php;
}

Ребят, а на сколько важен порядок передачи параметров fastcgi_params?
Есть разница, если SCRIPT_NAME поменял местами с REQUEST_METHOD, т.е. если первый поставил выше второго, а не как в дефолтном файле fastcgi_params?

Почему спрашиваю?...
Заметил, что параметры в строке браузера почему-то дублироваться стали. Т.е. запрос вида www.mysite.ru/index.php?option=com_content&view=article&id=1 у меня с недавнего времени стал выглядеть таким образом:
http://www.mysite.ru/index.php?option=com_content&view=article&id=1?option=com_content&view=article&id=1
До изменений порядка следования параметров такого не замечал. Потому других идей у меня нету.
Откуда ветер: есть в joomla фишка для обработки ответов 404.
Создаёшь статью в админке с текстом, который хочешь показывать при ответе 404. Т.е. чтоб это было в дизайне текущего шаблона, чтоб пользователь не пугался белого экрана с надписью 404 Not Found и не убегал с сайта.
Запоминаешь ID этой статьи.
Кладёшь в папку с шаблоном файл error.php с содержимым:
<?php
defined( '_JEXEC' ) or die( 'Restricted access' );
if ($this->error->code = '404') {
$URL='http://'.basename($_SERVER['DOCUMENT_ROOT'])."/index.php?option=com_content&view=article&id=1"; // id=1 - та самая статья, которую предварительно создал...
header($_SERVER["SERVER_PROTOCOL"]." 404 Not Found");
header("Location: $URL");
exit();
}
?>

И всё, если возвращается код 404, то появляется вот эта статья. А вызывается она как раз сформированным запросом
$URL='http://'.basename($_SERVER['DOCUMENT_ROOT'])."/index.php?option=com_content&view=article&id=1"; // id=1 - та самая статья, которую предварительно создал...

Вот, блин, в браузере в адресной строке теперь почему-то параметры этого запроса двоятся, хотя обработка НЕ найденных файлов передаётся в именованный location, там код 404 нормально обрабатывается и статья отображается.
Настройки заглушки @joomla с этого сайта, приведённые для joomla 1.5.
Только очерёдность параметров fastcgi_param поменял.

Ещё вопрос:
Зачем в ниже приводимом куске нужен fastcgi_index index.php? Ведь он нужен для формирования переменной $fastcgi_script_name, если URI заканчивается слешем, а мы и так вполне конкретно определяем путь к скрипту в параметрах SCRIPT_NAME /index.php и SCRIPT_FILENAME $document_root/index.php

location @drupal {
fastcgi_pass unix:/tmp/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
---------------------------------------------------------------------------------------------------------------------
................
fastcgi_param SCRIPT_NAME /index.php;

Ну и самый крайний вопрос: зачем вообще делается эта замена в параметрах SCRIPT_NAME и SCRIPT_FILENAME? Цель какова?
Чтобы в случае, если, к примеру, нет файла http://www.site.ru/images/pic1.jpg, то заменить этот запрос и подсунуть ему http://www.site.ru/index.php? Так? Или если нет запрашиваемого каталога http://www/site.ru/modules/, то опять ему подсунуть файл /index.php?
Господа, можете объяснить, как это работает?

Лучше-бы вы конфиг показали

если SCRIPT_NAME поменял местами с REQUEST_METHOD

а если вернуть на место ?
fastcgi_param — это не заголовки, это серверные переменные окружения, порядок установки значения не имеет, если не ошибаюсь
с дублированием параметров, нужно опять-же конфиг смотреть
а еще лучше соберать nginx с --with-debug, и посмотреть лог, там можно весь процесс отследить, куда и что передается
я делаю обычно так, смотрю параметры текущей сборки
nginx -V
а потом ./configure с такими-же параметрами, только с другим именем бинарника, --sbin-path=/usr/local/sbin/nginxdbg и --with-debug
ну и потом запускаете nginxdbg, в конфиге только нужно будет дописать:
error_log path/to/debug.log debug;

fastcgi_index index.php;

проcто дефолтовый параметр, если в данном случае его убрать, ничего страшного не случится как и в обратном случае

зачем вообще делается эта замена в параметрах SCRIPT_NAME и SCRIPT_FILENAME? Цель какова? Чтобы в случае, если, к примеру, нет файла

вроде того, правда сейчас есть try_files, и это уже не очень актуально
про переменные можете почитать тут
http://yapro.ru/web-master/apache/2__rewritebase_i_rewritecond_direktivi.html

цитаты не выделяются почему-то

Лучше-бы вы конфиг показали

Конфиг сайта вот:
index index.php;

location = / {
include /etc/nginx/fastcgi_default;
}

location = /administrator/ {
include /etc/nginx/fastcgi_default;
}

location / {
try_files $uri @not_found;
}

location ~* \.(gif|jpg|jpeg|png|ico|css|ttf|js|pdf)$ {
try_files $uri =404;
expires 1d;
add_header Cache-Control public;
}

location ~ index\.php$ {
try_files $uri @not_found;
include /etc/nginx/fastcgi_default;
}

location ~* \.php$ {
error_page 404 = @not_found;
return 404;
}

location @not_found {
include /etc/nginx/fastcgi_joomla;
}

@fastcgi_default - стандартные параметры, передаваемые FastCGI-серверу
(SCRIPT_NAME $fastcgi_script_name; SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_index index.php;)
@fastcgi_not_found - изменённые по рекомендациям в этой статье параметры, передаваемые FastCGI-серверу
(SCRIPT_NAME /index.php; SCRIPT_FILENAME $document_root$/index.php; fastcgi_index - этот параметр убрал)

если SCRIPT_NAME поменял местами с REQUEST_METHOD

менял туда-обратно - ни на что не повлияло.

Блин, очепятка: не @fastcgi_not_found, а @fastcgi_joomla

И знаки @ тоже лишние. Надо так: fastcgi_default и fastcgi_joomla.
Прошу прощения за ошибки.

Прошу помочь разобраться.

Вот что удалось отловить в логе nginx при включенном уровне логирования debug.

Приходит запрос на несуществующий файл.
Запрос передаётся на обработку в именованный location @not_found (этого не видно из лога).

Далее начинаются какие-то манипуляции с регулярными выражениями, в соответствии с переданными FastCGI-серверу параметрами SCRIPT_NAME /index.php; SCRIPT_FILENAME $document_root$/index.php, а также выполняется обработка сгенерированного ядром joomla запроса при получении кода 404:
$URL='http://'.basename($_SERVER['DOCUMENT_ROOT'])."/index.php?option=com_content&view=article&id=1"

2010/11/06 17:08:50 [debug] 2009#0: *2229 http script regex: "^"
2010/11/06 17:08:50 [notice] 2009#0: *2229 "^" matches "/index.php", client: 130.209.239.6, server: simba.travel, request: "GET /index.php?option=com_content&view=article&id=1 HTTP/1.1", host: "simba.travel"
2010/11/06 17:08:50 [debug] 2009#0: *2229 http script var: "http"
2010/11/06 17:08:50 [debug] 2009#0: *2229 http script copy: "://www.simba.travel"
2010/11/06 17:08:50 [debug] 2009#0: *2229 http script var: "/index.php?option=com_content&view=article&id=1"
2010/11/06 17:08:50 [debug] 2009#0: *2229 http script regex end

Ну и дальше какие-то телодвижения, которые мне не понятны. И почему происходит дублирование ?option=com_content&view=article&id=1 тоже осталось для меня загадкой.
Вот весь кусок лога:

2010/11/06 17:08:50 [debug] 2009#0: *2229 event timer del: 9: 562401567
2010/11/06 17:08:50 [debug] 2009#0: *2229 generic phase: 0
2010/11/06 17:08:50 [debug] 2009#0: *2229 http script regex: "^"
2010/11/06 17:08:50 [notice] 2009#0: *2229 "^" matches "/index.php", client: 130.209.239.6, server: simba.travel, request: "GET /index.php?option=com_content&view=article&id=1 HTTP/1.1", host: "simba.travel"
2010/11/06 17:08:50 [debug] 2009#0: *2229 http script var: "http"
2010/11/06 17:08:50 [debug] 2009#0: *2229 http script copy: "://www.simba.travel"
2010/11/06 17:08:50 [debug] 2009#0: *2229 http script var: "/index.php?option=com_content&view=article&id=1"
2010/11/06 17:08:50 [debug] 2009#0: *2229 http script regex end
2010/11/06 17:08:50 [notice] 2009#0: *2229 rewritten redirect: "http://www.simba.travel/index.php?option=com_content&view=article&id=1?option=com_content&view=article&id=1", client: 130.209.239.6, server: simba.travel, request: "GET /index.php?option=com_content&view=article&id=1 HTTP/1.1", host: "simba.travel"
2010/11/06 17:08:50 [debug] 2009#0: *2229 http finalize request: 301, "/index.php?option=com_content&view=article&id=1" 1
2010/11/06 17:08:50 [debug] 2009#0: *2229 http special response: 301, "/index.php?option=com_content&view=article&id=1"
2010/11/06 17:08:50 [debug] 2009#0: *2229 http set discard body
2010/11/06 17:08:50 [debug] 2009#0: *2229 HTTP/1.1 301 Moved Permanently
2010/11/06 17:08:50 [debug] 2009#0: *2229 write new buf t:1 f:0 081A1770, pos 081A1770, size: 270 file: 0, size: 0
2010/11/06 17:08:50 [debug] 2009#0: *2229 http write filter: l:0 f:0 s:270
2010/11/06 17:08:50 [debug] 2009#0: *2229 http output filter "/index.php?option=com_content&view=article&id=1"
2010/11/06 17:08:50 [debug] 2009#0: *2229 copy filter: "/index.php?option=com_content&view=article&id=1"
2010/11/06 17:08:50 [debug] 2009#0: *2229 http postpone filter "/index.php?option=com_content&view=article&id=1" 081A1930
2010/11/06 17:08:50 [debug] 2009#0: *2229 write old buf t:1 f:0 081A1770, pos 081A1770, size: 270 file: 0, size: 0
2010/11/06 17:08:50 [debug] 2009#0: *2229 write new buf t:0 f:0 00000000, pos 080CE280, size: 132 file: 0, size: 0
2010/11/06 17:08:50 [debug] 2009#0: *2229 write new buf t:0 f:0 00000000, pos 080CE0C0, size: 46 file: 0, size: 0
2010/11/06 17:08:50 [debug] 2009#0: *2229 http write filter: l:1 f:0 s:448
2010/11/06 17:08:50 [debug] 2009#0: *2229 http write filter limit 0
2010/11/06 17:08:50 [debug] 2009#0: *2229 writev: 448
2010/11/06 17:08:50 [debug] 2009#0: *2229 http write filter 00000000
2010/11/06 17:08:50 [debug] 2009#0: *2229 copy filter: 0 "/index.php?option=com_content&view=article&id=1"
2010/11/06 17:08:50 [debug] 2009#0: *2229 http finalize request: 0, "/index.php?option=com_content&view=article&id=1" 1
2010/11/06 17:08:50 [debug] 2009#0: *2229 http close request
2010/11/06 17:08:50 [debug] 2009#0: *2229 http log handler
2010/11/06 17:08:50 [debug] 2009#0: *2229 free: 081A10E0, unused: 1720
2010/11/06 17:08:50 [debug] 2009#0: *2229 close http connection: 9

а что у вас в /etc/nginx/fastcgi_default ?

Вот это:

fastcgi_pass unix:/var/run/php-fpm/default.socket;
fastcgi_index index.php;

fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;

fastcgi_param QUERY_STRING $query_string;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;

fastcgi_param REQUEST_METHOD $request_method;
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 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;

у меня на тестовом работает с таким конфигом:
версия Joomla! 1.6.0 Beta11 [ Hope ] 20-Sep-2010 23:00 GMT

root /20gb/joomla/public_html;

location / {
index index.php index.html index.htm;
}

location /administrator/ {
index index.php;
}

location ~* (/|\.html?|\.feed|\.pdf|\.raw|/[^.]*)$ {
try_files $uri $uri/ /index.php;
}

location ~* \.(gif|jpg|jpeg|png|ico|css|ttf|js|pdf)$ {
try_files $uri =404;
expires 1d;
add_header Cache-Control public;
}

location ~ \.php$ {
try_files $uri /index.php;
fastcgi_pass unix:/tmp/fastcgi.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

на дефолтовой установке джумлы с тестовым наполнением, вроде весь фенкционал присутствует и все работает
перепиливание шаблонного error.php под ваш вариант, приводит к ошибке:
Cannot access protected property JException::$code блаблабла
что-то вы с конфигом перемудрили

Так у меня joomla 1.5.22!!!

А не в курсе случайно, чтобы использовать в location параметр fastcgi_hide_header "Set-Cookie" обязательно задавать путь к FastCGI-серверу fastcgi_path?
Если задавать этот путь - получается передаём запрос серверу fastcgi. Ане хотелось бы этого делать, если нужно резать куки из статики (картинки, скрипты и т.п.). А с другой стороны, режем куки получая ответ от fastcgi, а не при передаче ему запроса. Нафига тогда вообще путь задавать? Но без fastcgi_path не работает. Как быть?

ну у меня только эта версия стоит, не думаю что разница значительна
fastcgi_path —нет в nginx такой директивы
а для чего резать куки, если вы не кэшируете ответы с fastcgi или proxy ?

Разница как раз есть.
По поводу того, что нет директивы fastcgi_path - да, согласен, есть fastcgi_pass. Не правильно написал, но имел в виду её, по этому вопрос о fastcgi_hide_header "Set-Cookie" остаётся в силе.
Куки мне нужно резать как раз для того, чтобы следующим шагом разобраться в кешировании и реализовать его.

Плюс инструменты разработчика в браузере Chrome постоянно рекомендуют отдавать статику с cookieless domain. Ну а я пытаюсь схитрож... ить и, не создавая отдельного домена, вырезать куки в location, где обрабатываются картинки и скрипты. Потому не хочу их передавать на обработку в FastCGI путём указания параметра fastcgi_pass, что, видимо, является обязательным условием для дальнейшего использования fastcgi_hide_header "Set-Cookie". Буду благодарен любому наставлению на путь истинный. :)

ну так когда будете кешировать, тогда и будете резать с помощью fastcgi_hide_header или proxy_hide_header
думаю вы не правильно понимаете суть, почитайте этот тред:
http://forum.nginx.org/read.php?21,99640

Господа, директивы rewrite где лучше писать? В server или в location?
Вот, к примеру, все запросы к файлам \.pdf надо перенаправить на обработку другому серверу.
Правило нужно писать в location или на уровне server?
Как правильнее и как лучше с точки зрения производительности сервера?
server {
...
rewrite ^(/.*\.pdf)$
$scheme://one.domain.net$1 permanent;
...
}

ИЛИ

server {
...
location ~* \.pdf$ {
rewrite ^ $scheme://one.domain.net$request_uri permanent;
}
...
}

второй вариан более гибкий и правильный, хотя оба рабочие

А с точки зрения "трудозатрат" сервера?

Рассуждаю так:
В первом варианте любой запрос к серверу сначала проверяется на соответствие директиве rewrite, а только потом передаётся на проверку в location. Т.е. прежде чем отдать какой-либо файл будет осуществлена проверка на соответствие директиве rewrite на уровне сервера. Вроде как лишние "телодвижения" для абсолютно всех отдаваемых файлов, кроме .pdf.

Во втором варианте прежде чем выполнить директиву rewrite сервер сначала прогонит запрос по всем location в порядке следования, пока дойдёт до того location, где прописана директива. Вроде тоже лишние "телодвижения" для файлов .pdf. Но таких запросов значительно меньше, чем всех остальных.

Видимо вопрос в том, что нужно отдавать чаще: файл .pdf или какие-либо другие, т.е. судить по частоте запросов.
Ну а если редирект на другой домен делается ДЛЯ ВСЕХ СТАТИЧНЫХ ФАЙЛОВ? Их также много, как и html! В этом случае имеется какой-либо выигрышь в производительности для одного и второго варианта?

сервер сначала прогонит запрос по всем location в порядке следования

не все location проверяются в порядке следования

обрабатывайте pdf в отдельном location, например как-нить так:

location ~* \.pdf$ {
  proxy_pass ......
  .....
}

ну или с тем-же rewrite вместо proxy_pass

Благодарю за рекомендации.

Возникло три вопроса.
Идея у меня маниакальная - избавиться от куки для статичных объектов путём передачи таких запросов другому виртуальному серверу (другой домен).
Ну, например, запросы картинок и каскадных таблиц стилей шаблона сайта приходят на domain.ru, а их надо передать на обработку в static.domain.ru (на том же IP и физическом сервере), только в static.domain.ru есть директива fastcgi_hide_header "Set-Cookie".
Исходя из этого:
1. Можно ли использовать proxy_pass, если бэкенд FastCGI-сервер, а не Апач и т.п.?
2. Если нельзя, то можно ли добиться внутреннего редиректа на другой виртуальный server, в котором задана конфигурация с отключенными cookies, используя fastcgi_pass, а не rewrite? Как?
3. Правильно ли я понимаю, что если с помощью proxy_pass (или fastcgi_pass) передаём запрос другому серверу, то после обработки запроса этот другой сервер возвращает ответ не напрямую клиенту, а первому серверу, который передал ему запрос? Если так, то идея избавиться от куки для статики путём обработки статичных объектов в другом сервере (другом домене) с отключенными куки будет невыполнима, т.к. в любом случае сервер отвечающий клиенту в заголовке ответа навяжет свои куки (от своего первого домена). Иными словами внутренний редирект при данной постановке задачи не поможет. Так?

Благодарю.

Здравствуйте, граждане!
Может кто-нибудь сможет мне помочь с такой проблемой. Хочу сайт перетащить на vps, но apache юзать нет желания, а сайт использует .htaccess с правилами для mod_rewrite. Все настроил за исключением этих правил и никак не могу понять, каким макаром их записать в конфиге nginx.
Собственно, сам файл .htaccess:

Options +FollowSymLinks
Options -Indexes
RewriteEngine on
RewriteCond %{REQUEST_URI} !\.(css¦js¦jpg¦gif)$
RewriteCond %{REQUEST_URI} ^/system.*
RewriteRule ^(.*)$ index.php?/$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php?/$1 [L]

Сайт сделан с помощью фреймворка codeigniter. Помогите, запарился уже...

что-то типа

location / {
  try_files $uri $uri/ /index.php?$request_uri;
}

location ~* ^.+\.(css|js|jpg|gif)$ {
}

Спасибо, попробуем на деле..

В общем, правила роутинга, указанные внутри CI, не работают, то есть, переходя по ссылкам на главной странице (которые [ссылки] уже настроены по внутреннему роутингу), выдается ошибка 404. Сама главная вроде открывается. Нужно заставить работать внутренний роутинг иначе вообще не имеет смысла использовать этот фреймворк с nginx.

Забыл добавить, что на нынешнем хостинге все работает. Но тут, похоже, юзается апач на бак-эндах. Вот без апача бы заставить все это дело работать.

Нашел временное (и скорее всего неверное) решение:
$config['permitted_uri_chars'] = '' ;
закоментировав предварительно оригинальное решение.
Подскажите, если кто знает, как сделать более корректно.

Отправить комментарий

Содержание этого поля является приватным и не предназначено к показу.
Регистр имеет значение
       .o     o8o                       .oooo.    ooooooooo.    ooooooooo.   
.d88 `"' .dP""Y88b `888 `Y88. `888 `Y88.
.d'888 oooo oooo oooo ooo ]8P' 888 .d88' 888 .d88'
.d' 888 `888 `88. `88. .8' <88b. 888ooo88P' 888ooo88P'
88ooo888oo 888 `88..]88..8' `88b. 888`88b. 888
888 888 `888'`888' o. .88P 888 `88b. 888
o888o o888o `8' `8' `8bd88P' o888o o888o o888o


Введите код, изображенный в стиле ASCII-арт.