検索結果アドレスを静的 URL に書き換える時の問題点

サイト内検索の結果を表示するページのアドレスを静的 URL にしたい。何よりスッキリするし、アーカイヴやカテゴリやタグなどのアドレスとの調和もとれる。そのような思い付きでいろいろとやってみたのですが、細々とした問題が生じてしまう様子。

目次
  1. 書き換えのプロセス
  2. 問題点
    1. [NE] フラグ
    2. %2F 問題
    3. AllowEncodedSlashes ディレクティブ

書き換えのプロセス

動的アドレスを静的アドレスに見せかけるよく知られた方法に、Apache の mod_rewrite モジュールを利用したものがあります。それは、httpd.conf や .htaccess ファイルに記述した書き換えルールに基づき、静的アドレスでのアクセスがあった場合でも、実際には本来の動的アドレスとして処理されるようにする仕組みです。

上のアドレスでアクセスがあった時、実際には下のアドレスとして動作させるというわけです。件の検索結果アドレスの静的化もその方法で可能だと考えていました。次のようなプロセスで簡単に実現できるはずだと。

  1. フォームの送信データを静的アドレスに書き換える
  2. 書き換えられた静的アドレスへリダイレクトさせる
  3. 静的アドレスをクエリストリングの形に書き換える

問題点

この方法での問題点は、パーセントエンコーディング (URL エンコーディング) にあります。「hoge」ではなく、日本語で「ほげ」と検索した場合、静的化したアドレスが次のようになってしまう (文字コードは UTF-8)。

「ほ」が「%E3%81%BB」となって「%25E3%2581%25BB」に。「%」の部分が「%25」へと二重に変えられてしまっているのです。この挙動は、「%」「?」「&」などの特殊文字をエスケープするというデフォルト設定があるために起こります。

[NE] フラグ

そこで、RewriteRule のオプションである NE (noescape) フラグを使うことにしました。こうすることで「%」はエスケープされずに済み、アドレスをデコードして表示するブラウザなどでは、ロケーションバーに次のように表示されます。

うまくいきました。

%2F 問題

が、NE フラグを使った代償として別の問題が生じます。検索語にスラッシュ「/」を含めることができなくなりました。いわゆる「%2F 問題」です。

スラッシュ「/」は %2F にエンコーディングされますが、Apache は、URL に %2F が含まれていると 404 Not Found を返します。今回 RewriteRule に NE フラグを付けたことで、「%」はエスケープされなくなり、スラッシュは %2F のままに。結果、404 エラーとなってしまうのです。

NE フラグを外せば %2F は %252F となるのでもちろんエラーは出ませんが、最初の例のごとく、パーセントエンコーディングされる他の文字の % も全て %25 に置き換えられてしまいます。

AllowEncodedSlashes ディレクティブ

このジレンマは、AllowEncodedSlashes ディレクティブで解消できます。これは、符号化されたパス分離文字が含まれる URL の使用を許可するか否かを決定するディレクティブです。

AllowEncodedSlashes On

上記コードをサーバ設定ファイル (httpd.conf など) に書くことで、NE フラグを付けたまま「ほ/げ」を検索してもエラーは出現しません。

ただし、AllowEncodedSlashes ディレクティブは、.htaccess ファイルでは使用できないということに注意が必要です。つまり、レンタルサーバーだから httpd.conf が編集できないといった場合、この方法は使えません。

今日学んだこと

検索結果ページを静的 URL 化する時の問題点。AllowEncodedSlashes は .htaccess ファイルには使用できない。