クエリ文字列の疑問符をアンダースコアに置き換えるNginx書き換えルール


16

ウェブサイト全体を静的なHTMLとしてミラーリングするには、

私は次のようなURLに変換したいhttp://example.com/script.php?t=12http://example.com/script.php_t=12

?URLの通知はに変換されてい_ます。

これにより、nginxまたはapache wgetは、PHPファイルとしてではなく、取得して保存した生のHTML(URLごとに1つのファイル)としてこれらのファイルをディスクから提供できます。

Nginx URL書き換えを使用してこれを行うことは可能ですか?


確かに可能ですが、本当に奇妙です。何のために欲しい?
アレクセイ

2
このアプローチの1つの問題は、URL内の複数のGETパラメーターが任意の順序になる可能性があることです。この変換を行うと、URLのセマンティクスが変更されます。
テロキルカネン

古いフォーラムを静的なhtmlでアーカイブするためですが、この作業を行うにhttp://example.com/script.php?a=1&t=3は、超豪華な書き換えアクションが必要になります
サムサフラン

1
@teroのクエリ文字列URLは、実際には常に同じ順序です。したがって、これは問題ではありません。
ジェフアトウッド

1
引数以外のことができるよう@chxそれは、旧フォーラムのアーカイブのためだtようなfuなど
Arpitジャラン

回答:


15

私はtry_filesを使用してこれを機能させました:

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

これは、「?」ではなく「_」を指定したパターンにちなんで名付けられたディスク上のファイルを見つけようとします。

さらなる設定は、画像やスタイルシートなどの静的ファイルを保存した方法に依存します。次のようなディスクからのクエリ文字列なしでそれらを読み取ろうとするフォールバックを追加できます。

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

1
非常に興味深いアプローチですが、潜在的なすべてのURLで潜在的なディスク読み取りと「ファイルが見つかりません」が発生しますか
ジェフアトウッド

try_filesから:「指定された順序でファイルの存在を確認し、最初に見つかったファイルを要求処理に使用します」。したがって、これにより、質問内のURLに対する追加のディスク読み取りは発生しません。
マティアスバイエル

1
わかりました、location ~ \.php$私たちはそれを入れればtry_files仕事にlocation /
ジェフアトウッド

+1中かっこを使用する場合の例:)
ダニラヴァーシニン

4

線に沿って何か:

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

?使用した私の答えは省略しました。
chx

あなたの答えは?に関しては正しいです。実サーバでテストするのに時間がかかりました。そして、あなたのものは、望ましくないかもしれない「_」でバリアントへの引数なしでさえ、すべてのURLを書き換えます。
マックスガシコフ

try_filesを使用したMatthiasのソリューションは、実際にはこれよりも望ましい方法です。
マックスガシコフ

.*最初の書き換えパラメータでより厳密な句を指定する場合、ifなしで実行できます。これは非常に役立ちます!
ジェフアトウッド

@JeffAtwood可能性はないと思います。nginxの書き換え(および場所)パターンは、クエリ文字列の前にのみURLの一部に適用する必要があります。
マックスガシコフ

1

バニラnginxでこれを行うことはできないと思いますが、nginxのLuaモジュール(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({})

1

これはnginx / 1.6.2で動作します。

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

しかし、個人的には、もしあればtry_files元のURIへのフォールバックを伴うソリューションを使用します

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

たとえば、script.phpディスク上にある場合は、最初に試してみて、次に何もない場合は、に進みますscript.php_t=12try_filesnginxの最新バージョンが必要です。

これで十分でない場合は、次のようにできますif

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

私はこれが好きですが、try_filesビットを実際に機能させることはできませんが、書き換え機能します。(まあ、?そこにリライトの最後にa を追加すると、クエリパラメータは追加されません。)
ジェフアトウッド

@JeffAtwood try_filesは、それと$uri一致するロケーションブロック、またはそのファイル(引数を取得しないリクエスト)がある場合に停止します-そうですか?
AD7six

@JeffAtwood ?は静的ファイルに対して目に見える効果はありません。アクセスログには追加のクエリのみが表示されます。気になる場合は、疑問符を追加してください
sanmai

0

Wikiは言います

?を指定した場合 書き換えの最後に、Nginxは元の$ args(引数)を削除します。

それでrewrite ^ ${uri}_$args? last;動作するはずです。


nginxはそのルールセットで再起動に失敗しますrewrite ^ $uri_$args? last;
ジェフアトウッド

修繕。$ -bleeds-over-the-variablesはPHPのように感じます。
chx

修正版でも、nginxの再起動に失敗します
ジェフアトウッド

0

上記の提案された答えはうまくいくはずです。ただし、URLがどれほど敏感になっているかがわかります。nginxは最初にファイル名がサーバー上に存在するかどうかを確認しようとするため、追加のパラメーターはそれをスローします。

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

私の提案は、URLをそのままにして、phpで正しいファイルにルーティングすることです。tパラメータにアクセスできます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.