Sorgu dizesi soru işaretini alt çizgi ile değiştirmek için Nginx yeniden yazma kuralı


16

Bir web sitesinin tamamını statik HTML olarak yansıtmak için,

Ben gibi URL'leri dönüştürmek istiyoruz http://example.com/script.php?t=12için http://example.com/script.php_t=12.

?URL'deki bildirim dönüştürülüyor _.

Bu, nginx veya apache'nin bu dosyaları diskten wgetbir PHP dosyası yerine elde ettiğimiz ve kaydettiğimiz ham HTML olarak - her URL için bir dosya - sunmasına izin verecektir .

Nginx URL yeniden yazma yoluyla bunu yapmak mümkün müdür?


Kesinlikle mümkün, ama gerçekten garip. Ne için istiyorsun?
Alexey Ten

2
Bu yaklaşımla ilgili bir sorun, bir URL'deki birden fazla GET parametresinin herhangi bir sırada olabilmesidir ve bu dönüşümü yaptığınızda, URL'nin anlambilimini değiştirirsiniz.
Tero Kilkanen

onun statik html eski bir forum arşivlemek için, ama evet bu çalışma sahip http://example.com/script.php?a=1&t=3bazı süper süslü yeniden yazma eylem ihtiyacı olacak
Sam Saffron

1
@tero sorgu dizesi URL'leri pratikte her zaman aynı sıradadır. Yani bu bir sorun değil.
Jeff Atwood

1
argüman dışında olabilir böylece @chx o eski forumu arşivleme için var tgibi f, uvb
Arpit Jalan

Yanıtlar:


15

Try_files kullanarak bu çalışma var:

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

Bu, diskte "?" Yerine "_" sağladığınız kalıbın adını taşıyan bir dosya bulmaya çalışacaktır.

Daha fazla yapılandırma, görüntü veya stil sayfası gibi statik dosyaları nasıl kaydettiğinize bağlıdır. Aşağıdaki gibi sorgu dizesi formu diski olmadan bunları okumaya çalışırken bir yedek ekleyebilirsiniz:

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

1
çok ilginç bir yaklaşım, bu tüm potansiyel URL'lerde potansiyel bir disk okuma ve "dosya bulunamadı" neden olur?
Jeff Atwood

Try_files Gönderen : "Belirtilen sırayla dosyaların varlığını kontrol eder ve istek işleme için bulunan ilk dosyayı kullanır". Dolayısıyla bu, sorunuzdaki URL'ler için ek disk okumalarına neden olmaz.
Matthias Bayer

1
Tamam, eğer koyarsak işe location ~ \.php$başlayabiliriz try_files, ama işe yaramazlocation /
Jeff Atwood

Kıvırcık parantez kullanma örneği + 1 :)
Danila Vershinin

4

Çizgiler boyunca bir şey:

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

Dışarı sol ?kullanılan cevabımı.
chx

Cevabınız için? İle ilgili haklısınız - gerçek sunucuda test etmem biraz zaman aldı, bu yüzden benimkini gönderene kadar sizinkini görmedim. Ve sizinki, "_" değişkeniyle argüman olmadan bile tüm URL'leri istenmeyen bir şekilde yeniden yazacaktır.
Max Gashkov

Matthias'ın try_files ile çözümü aslında buna daha çok tercih edilir.
Max Gashkov

.*ilk yeniden yazma parametresinde daha katı bir madde belirlediğimizde, if olmadan yapabiliriz . Bu son derece yararlı!
Jeff Atwood

@JeffAtwood Bunun mümkün olduğunu düşünmüyorum - nginx yeniden yazma (konumun yanı sıra) kalıpları yalnızca sorgu dizesinden önce bir URL'nin bir bölümüne uygulanmalıdır.
Max Gashkov

1

Bunu vanilya nginx ile yapabileceğinizi sanmıyorum, ancak nginx için Lua modülünü kurmaya hazırsanız ( http://wiki.nginx.org/HttpLuaModule ) bunu yapabilirsiniz.

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({})
        ';

    }
}

Yerel olarak test edildi ve aradığınızı yapıyor gibi görünüyor. Diğer parametrelerin ve işaretleri ile ayrılmasını istiyorsanız, rewrite_by_lua bloğunu

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({})

1

Bu nginx / 1.6.2 üzerinde çalışır.

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

Ama kişisel olarak , eğer varsatry_files orijinal bir URI'ye geri dönüş ile çözüm kullanırdım .

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

Örneğin script.php, diskte varsa önce bunu deneyecek ve daha sonra, eğer yoksa, gidecek script.php_t=12. try_filesson zamanlarda yeterli bir nginx sürümü gerekiyor.

Ve eğer bu yeterli değilse, bunu şu şekilde yapabilirsiniz if:

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

Bunu beğendim ama yeniden yazma oysa biz, try_files aslında iş için bit alamayan yapar işi. (iyi, ?orada yeniden yazma işleminizin sonuna a eklerseniz sorgu parametreleri buna eklenmez ..)
Jeff Atwood

@JeffAtwood try_files, bununla $urieşleşen bir konum bloğu veya bunun için bir dosya (alma bağımsız değişkenleri olmadan istek) varsa duracaktır - durum böyle mi?
AD7six

@JeffAtwood'un ?statik dosyalar üzerinde görünür bir etkisi yoktur, erişim günlüklerinizde yalnızca fazladan bir sorgu görürsünüz; Eğer bunu önemsiyorsanız, bir soru işareti ekleyin
sanmai

0

wiki diyor

Bir? yeniden yazmanın sonunda Nginx orijinal $ args (argümanlar) bırakacaktır.

O zaman rewrite ^ ${uri}_$args? last;çalışmalı.


nginx bu kural seti ile yeniden başlayamaz -rewrite ^ $uri_$args? last;
Jeff Atwood

Sabit. Değişkenlerin üzerinde $ -bleeds-sadece sevdiğini biliyorum PHP gibi geliyor.
chx

gözden geçirilmiş versiyonda bile, nginx yeniden başlatılamıyor
Jeff Atwood

0

Yukarıda önerilen cevaplar işe yaramalıdır. Ancak URL'nizin ne kadar hassas olduğunu görürsünüz. Nginx önce dosya adının sunucuda var olup olmadığını kontrol etmeye çalıştığından, fazladan herhangi bir parametre dosyayı atar.

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

Benim önerim URL'yi olduğu gibi bırakmak ve php ile doğru dosyaya yönlendirmektir. tParametreye erişiminiz var .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.