エンコードが合わないPOSTデータの破壊回避策

散文でごめんなさい。ごめんなさい。

半分戒めです。ごめんなさい。

技術的には低レベルな話です。ごめんなさい。

環境

クライアントサイド
サーバサイド
  • LinuxCentOS
  • Apache2.?
  • Python2.6.4
  • DJango1.2b(リポジトリの最新版使った)
  • MySQL5.?(今回関係ないけど、書いとく)

発生事象

サーバサイドの文字コードutf-8で統一して設定してる。

そんでIE7君がEUC-JPのHTMLを読み込んでPOSTすると、EUC-JP送っているようでDJangoのrequest.POSTで受けると文字化けする。というか完全にぶっ壊れて\ufdddとなる。なぜ??

ちなみにFirefox3.5だとutf-8で送ってくれて壊れない。

回避策1(失敗)

要件上、HTMLのmeta要素charset属性やHTML自体の文字コードはいじれない。なのでeuc-jp。

form要素のaccept-charset属性に文字コードを指定するとうまくいくらしい記事を発見し、utf-8で検証。[http://0xcc.net/pub/webdb/bk-04.html:title=BK通信 - ブラウザのバッドノウハウ

編]

結果、IE7君はダメでした。euc-jpで送りやがった。こんちくしょう。

パケットキャプチャのWiresharkでHTTPキャプチャみたりもした。。。

input要素のtype属性hiddenで_charset_を設定すると効くよ!ってさっきの記事[http://0xcc.net/pub/webdb/bk-04.html:title=BK通信 - ブラウザのバッドノウハウ 編]
に書いてあったので、検証。

結果、IE7君はだめ。euc-jpだた。



回避策2(失敗)

今度はサーバサイドでエンコードすればいいんじゃね??ってことでトライしたけど、Djnagoに辿りついてる時点で文字列がぶっ壊れてu'\ufddd'だ...

Apachemod_pythonが悪さしてそうでもないし...。頭がパンクしそうでお手上げ。



回避策3(成功)

困ったのでクライアントサイドとサーバサイドで連携し回避することに。

JavaScriptのencodeURIComponentで処理した後、input要素のvalueにデータを格納し、form.submit()でPOSTした。

クライアントサイドのJavaScript

/*
(ry
*/

サーバサイドのPythonでは、

euc_jp_str = u'エンコードされたEUC-JPの文字列'
string_str = str(euc_jp_str) # string型に変換
import urllib
utf8_str = urllib.unquote(string_str).decode("utf-8") # アンクォートした後utf-8デコード。

これすれば文字コードは関係なさそう。

課題

課題は山積み。

  • ドメインまたいだりしてる。Djangoでは一部CSRFをoffにした...。セキュリティ不安。
  • そもそもJavaScript動かなかったらPOSTできない。どうしよう...。
  • Apacheの処理、mod_pythonの処理、DjangoのHTTPRequestの処理をもっと追わないといけないな。

疑問

  • そもそもこの対応策以外によい策があるんでは...?

愚痴

  • HTMLのmeta要素やHTMLの文字コードをさわらせない外部のサービスを使ってたのが痛い。大規模じゃないんだから構築し直したい...。
    • その外部のサービスがEUC-JP使ってるとかもう辛い。


久々に叫びたくなった。実力不足に(ry

追記

tokibito氏が助け舟を出してくれた。
WSGIHandler.request_classに独自実装し、回避したのを当てるとよいとのこと。
http://bitbucket.org/tokibito/django-bpmobile/src/tip/bpmobile/__init__.py