YiiFramework избавиться от /index.php

grigori

( ͡° ͜ʖ ͡°)
Команда форума
нужно сделать редирект с /index.php[/.*] на /(1)
чтобы http://site.ru/index.php/my_product_page редиректило на http://site.ru/my_product_page

showScriptName=>false в конфиге - это понятно, но если такие ссылки уже проиндексированы, нужно отдавать 301

средствами nginx это оказалось не так-то просто, потому что на index.php идет внутренний редирект, и просто написать location /index.php {return 301 /;} нельзя - получается рекурсия.

решил вот так:

Код:
server {
    server_name  localhost vm;
    root  /www;
    set $yii_bootstrap "index.php";
    set $fsn false;

    location / {
        #unexisting file
        index /index;

        try_files $uri @php;
    }

    location ~ ^/index.php/?(.*)? {
        return 301 /$1;
    }

    location ~ \.php {
        fastcgi_split_path_info  ^(.+\.php)(.*)$;
        set $fsn $fastcgi_script_name;
        try_files false @php;
    }

    location @php {
        if ($fsn = false){
                set $fsn /$yii_bootstrap;
        }
        include fastcgi_params;

        fastcgi_param  SCRIPT_FILENAME  $document_root$fsn;
        fastcgi_pass  127.0.0.1:9000;
    }
}
Это интересно:
* вызов include fastcgi_params; не получается вынести на уровень server;
* при передаче обработки вызова на именованный location через try_files false @php; значения переменных ($fsn) сохраняются, а на обычный, вида try_files $uri /index.php - идет обработка директив set, которые стоят в контексте server.
 
Последнее редактирование:

MiksIr

miksir@home:~$
Я такой конфиг юзаю.
Код:
root $lroot;

location ~ ^/(favicon.ico|robots.txt)$ {
        try_files $uri =404;
}

# Если хотим исполнять доп. скрипты - то fastcgi, иначе нужно
# что-то вернуть (404), что бы по запросу не отдавались исходники
location ~ \.php$ {
#        try_files $uri @index;
#        fastcgi_pass $fserver;
#        set $fname $fastcgi_script_name;
#        include /etc/nginx/inc/fastcgi.inc;
          return 404;
}

location / {
    try_files $uri @index;
}

location ~ ^/(js|images|assets|static|upload)/ {
        root $lroot;
}

location @index {
        fastcgi_pass $fserver;
        set $fname /index.php;
        expires -1;
        include /etc/nginx/inc/fastcgi.inc;
}
$fname используется в fastcgi.inc
fastcgi_param SCRIPT_FILENAME $document_root$fname;
fastcgi_param SCRIPT_NAME $fname;

Соответственно, для запрошенного редиректа я бы написал
Код:
location /index.php {
   rewrite /index.php(.*) $1 permanent;
}
 

grigori

( ͡° ͜ʖ ͡°)
Команда форума
MiksIr, да, ты прав, в location / проще написать прямо
try_files $uri @php;
т.е. не обрабатывать полностью внутренний редирект, а просто отправить на именованный location. Тогда и в location ~ ^/index.php не нужна проверка на редирект.
Спасибо за подсказку.
 
Последнее редактирование:

grigori

( ͡° ͜ʖ ͡°)
Команда форума
Один момент:
Код:
location / {
    try_files $uri @index;
}
location /index.php {
   rewrite /index.php(.*) $1 permanent;
}
тут нет index /index.php;
а если написать
Код:
        location / {
                index /index.php;
                try_files $uri $uri/ @php;
        }
        location ~ ^/index.php/?(.*)? {
                return 301 /$1;
        }
т.е. проверка на $uri/ вместе с директивой index - это рекурсия. не могу сходу сообразить почему.

Если написать
location /index.php { return 301 /;}
location ~ \.php {fcgi_pass ...}
в 1.4 редирект отработает, и даже зацикливания c index не будет,
а в 1.5 редирект не отрабатывает, обработка уходит на регексп, нужно
location ^~ /index.php :) и будет рекурсия

в nginx столько подводных камней, да еще и поведение между версиями различается
 
Последнее редактирование:

MiksIr

miksir@home:~$
А зачем index? Там в именованном локейшене по сути fastcgi_param SCRIPT_FILENAME $document_root/index.php; fastcgi_param SCRIPT_NAME /index.php; т.е. вне зависимости от URI вызов уходит на yii-шную точку входа.

т.е. проверка на $uri/ вместе с директивой index - это рекурсия. не могу сходу сообразить почему.
Вот не уверен после выходных, но вроде так: Запрос на корень с помощью $uri/ части try_files и index index.php ресолвится в /index.php, потом внутренний редирект, этот запрос попадает в location ~ ^/index.php/?(.*)? и как результат (т.к. $1 пустое) - 301-й редирект на /. Вот и цикл.
 

fixxxer

К.О.
Партнер клуба
Да, так и есть. Можно сделать ^/index.php(/.*)$ и сделать так, чтобы слеш всегда был. Если туда подставляется $uri - он будет всегда.

Но я бы сделал иначе.

Держать в root *.php - это вообще зло. Если уж исторически сложилось, что есть какие-нибудь /scriptName.php, которые вот так напрямую вызываются - то ладно. Но при единой точке входа вообще в этом нет смысла.

Если же, скажем, структура такая:

/path/to/app/www/ - тут статика, assets итд;
/path/to/app - тут вне подкаталога www нет ни одного файла, который отдается напрямую

то все становится намного более управляемо, и пишется напрямую as-is безо всяких хаков.

app.conf

PHP:
server {
    ...
    set $app_root /path/to/app;
    set $app_uri "/";
    root /path/to/app/www;
    ...

    location / {
        try_files $uri @php;
    }

    location /index.php {
        location ~ ^/index\.php(/.+)$ {
            set $app_uri $1;
            include app.fcgi.conf;
        }
        location ~ ^ {
            return 301 /;
        }
    }

    location @php {
        set $app_uri $uri;
        include app.fcgi.conf;
    }

}
app.fcgi.conf

PHP:
fastcgi_param DOCUMENT_ROOT $app_root;
fastcgi_param PATH_INFO $app_uri;
fastcgi_param REQUEST_URI $app_uri;
fastcgi_param SCRIPT_NAME /index.php;
fastcgi_param SCRIPT_FILENAME $app_root/index.php;

#... остальные параметры и fastcgi_pass
UPD: А, 301 надо отдавать для /index.php/*. Тогда еще проще:
PHP:
    location /index.php {
        location ~ ^/index\.php(/.+)$ {
            return 301 $1;
        }
UPD2: если нужно сохранять query string, то return 301 $1$is_args$args.

UPD3: Вообще нет смысла молиться на стандартный /etc/nginx/fastcgi_params как на священную корову, возможность явно определить все fastcgi-параметры в nginx очень удобна, и выгодно его выделяет на фоне других серверов. Нет ничего плохого в том, что для каждого приложения он свой.
 
Последнее редактирование:

grigori

( ͡° ͜ʖ ͡°)
Команда форума
fixxxer, да, вынесение статики упрощает жизнь, толковая идея, спасибо, это несколько упрощает деплоймент.

кажется, в yii есть какие-то соглашения насчет docroot, что assets лежит рядом с бутстрапом, но это должно быть настраиваемо

*.php есть, но их можно вынести в третью папку
 

fixxxer

К.О.
Партнер клуба
кажется, в yii есть какие-то соглашения насчет docroot, что assets лежит рядом с бутстрапом, но это должно быть настраиваемо
В крайнем случае, появится еще location /assets/ { root $app_root }, ничего страшного. Но я не верю, что там хардкод, я понимаю, что это yii, но не настолько же :)
 
Сверху