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

Правило перезаписи Nginx для замены вопросительного знака в строке запроса на подчеркивание

Чтобы отразить весь веб-сайт как статический HTML,

Я хотел бы преобразовать URL-адреса типа http://example.com/script.php?t=12 к http://example.com/script.php_t=12.

Уведомление ? в URL преобразуется в _.

Это позволит nginx или apache обслуживать эти файлы с диска как необработанный HTML-код, который мы получили и сохранили из wget - один файл для каждого URL-адреса, а не как файл PHP.

Можно ли сделать это с помощью перезаписи URL-адресов Nginx?

Я получил эту работу с помощью try_files:

location / {
    try_files "${uri}_${args}" 404.html;
}

Это попытается найти на диске файл, названный в соответствии с указанным вами шаблоном с «_» вместо «?».

Дальнейшая конфигурация зависит от того, как вы сохранили статические файлы, такие как изображения или таблицы стилей. Вы можете добавить резервный вариант, пытаясь прочитать их без диска формы строки запроса, например:

location / {
    try_files "${uri}_${args}" $uri 404.html;
}

Что-то вроде:

location ~ \.php$ {
  # only rewrite URL's with args
  if ($args != '') {
    rewrite .* "${uri}_${args}?" last;
  }
}

Я не думаю, что вы сможете сделать это с помощью vanilla nginx, но если вы хотите установить модуль Lua для nginx (http://wiki.nginx.org/HttpLuaModule) ты можешь это сделать.

server {
    server_name so.dev;
    listen 80;

    location / {

        root /tmp;

        rewrite_by_lua '
            local uri = ngx.var.uri
            local params = ngx.req.get_uri_args(0)

            for key, value in pairs(params) do
                uri = string.format("%s_%s=%s", uri, key, value)
            end

            ngx.req.set_uri(uri)
            ngx.req.set_uri_args({})
        ';

    }
}

Протестировал локально и, похоже, делает то, что вы ищете. Если вы хотите, чтобы другие параметры были разделены амперсандами, измените блок rewrite_by_lua на

local uri = ngx.var.uri
local param_string = ""
local params = ngx.req.get_uri_args(0)
local separator = ""

for key, value in pairs(params) do
    param_string = param_string .. separator .. key .. "=" .. value
    separator = "&"
end

ngx.req.set_uri(uri .. "_" .. param_string)
ngx.req.set_uri_args({})

Это работает на nginx / 1.6.2.

rewrite ^/.*\.php$ "${uri}_${args}";

Но лично я бы использовал try_files решение с откатом к исходному URI если есть.

try_files $uri "${uri}_${args}";

Например. если у вас есть script.php на диске он сначала попробует с ним, а затем, если его нет, он пойдет script.php_t=12. try_files нужна последняя версия nginx.

А если этого недостаточно, можно сделать это внутри if:

return 301 "${uri}_${args}";

В вики говорит

Если вы укажете? в конце перезаписи Nginx отбросит исходные $ args (аргументы).

Итак, тогда rewrite ^ ${uri}_$args? last; должно сработать.

Предложенные выше ответы должны работать. Однако вы видите, насколько чувствительным становится ваш URL. Поскольку nginx сначала пытается проверить, существует ли имя файла на сервере, любой дополнительный параметр отбросит его.

http://example.com/script.php?t=12 // works 
http://example.com/script.php?t=12&_utm=twitter // not work

Я предлагаю оставить URL как есть и направить его в файл с помощью php. У вас есть доступ к t параметр.