Tornadoを使ってたら、URLパラメータのエスケープ/アンエスケープ周りで不可解な挙動があったため、ソースを読んでみたらタイトルの通り、パラメータをリクエストハンドラに渡す前にunquoteする作りになってました(バージョン1.1 )。
ソースが短いから読みやすくてイイ。
不可解な挙動というのは、TornadoではテンプレートでURLパラメータを出力する際、url_escapeというテンプレート関数を使ってエスケープするのが普通だと思うのですが、url_escapeは内部でurllib.quote_plusを使ってるんですね。
つまり、リクエストハンドラ内では、元の文字列をquote_plusしたものをunquoteしたパラメータを受け取るわけで、パラメータに半角スペースと「+」記号が入ってるとおかしな事になる訳です。
例えば u”ai+u eo” という文字列をquote_plusすると u”ai%2Bu+eo” となります。それをunquoteすると%2Bは元に戻してくれますが、「+」記号は元に戻してくれないため u”ai+u+eo” となってしまいます。
ここまで来てしまうとリクエストハンドラ内だけではもう元の文字列を正確に再現する術がありません。
どーすんのよコレw
コレの解決方法は、
1. スペースを別の文字に置換してからquote_plus、unquoteされてきたモノをハンドラ内で復元する。
2. 1と同じような方法で、quote_plusしてさらにquoteする。unquoteされてきたモノをハンドラ内でunquote_plusする。
3. tornado/web.pyをいじって勝手にunquoteしないようにする。もしくはunquote_plusにする。
4. tornado.escape.url_escapeでquote_plusじゃなくてquoteを使うようにする。
という4パターンを思いつきました。
一番スマートそうな4をやってみました。
tornado/escape.py を直接いじるのはアレなので、tornado webサーバー起動時に必ず読み込まれるモジュール内に以下を記述しました。
import urllib from tornado import escape def url_escape(value, quote_plus = True): """Returns a valid URL-encoded version of the given value.""" if quote_plus: return urllib.quote_plus(escape.utf8(value)) # quoteはデフォで'/'をクオートしないため第二引数に空文字を渡して全部クオートするようにする return urllib.quote(escape.utf8(value), '') def url_unescape(value, unquote_plus = True): """Decodes the given value from a URL.""" if unquote_plus: return escape._unicode(urllib.unquote_plus(value)) return escape._unicode(urllib.unquote(value)) escape.url_escape = url_escape escape.url_unescape = url_unescape
関数のすり替えが簡単なので楽ですね。
これでテンプレートで url_escape(text, False) として使うと、いい感じにリクエストハンドラにパラメータが渡ってきます。
注意点は、web.pyでunquoteされる時はunicode化されないので必要ならハンドラ内でunicode化する必要があります。
またコメントで書いてますが、quoteはデフォルトで「/」をエスケープしないので第二引数を空文字にして、quote_plusのデフォルトに合わせてあります。
(quote_plus と quote は空白をどう置き換えるか以外にもどの文字を置き換えるかのデフォルト値が違います!)
最近のコメント
名前
しゅごい
Jane Doe
FYI Avoid Annoying Unexpe…
Jane Doe
ご存じとは思いますが、whileには、”~の間”と…
peta_okechan
針金みたいなパーツを引っ張ると外れます。 他の方の…
虎徹ファン交換
虎徹の標準ファンを外す際に、どのようにして外されま…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…
花粉症対策2019 – 日曜研究室
[…] 花粉症対策についてはこれまで次の記事を書いてきました。https://…