1)tDiaryなどのレガシーウェウアプリをRuby1.9で動かす方法
藤岡岳之さんの発表(発表スライドはこちら)
1.いかに1.9のcgi.rbが腐っていたか
1.8のcgi.rbは基本的に誰でも使うし、RoRでも使っていて基本的に動く
(Merbは使ってないけど)
ただし、各方面で現状の内容はよろしくないといわれている
1.8のcgi.rbはこんな点がだめ
- テストが無い
- マルチパート時のデータ受け取り方が酷い
- 遅い
1.9のcgi.rb
- 誰も使っていないし、だれもメンテナンスしてない
まだcgi.rbを使いたい
1.9でcgi.rbを使ってみる
- html出力は出たが、日本語が混ざると出ない
- M17Nでエラーが出ている(マジックコメントの追加)
- 「牛タン」の文字が表示されない!
- Content-Lendthが短く出力される!
- この時点で誰も使っていない事を確認。1.9.1では削除される危機
行動した事
- IRCに報告し、usaさんがfix
- 本格的に使うにはてこ入れ必要だった
てこ入れ
2.改良した結果cgi.rbはこうなった
cgi.rbを読んだ感想
- 通常使われていない機能が沢山使われている(継承よりDelegateを使ってる)
- スピードへの考慮が無い
- "aaa"+"bbb"より "aaa"<<"bbb"の方が早いんだが全く使われていない
大まかな変更点
- テストを追加
- CGI.newするときに受け取るエンコーディングを指定出来るように
- CGI.newにブロックを与えて例外処理を行える
- マルチパートのデータ受け取りはIO型では無くした
- CGI#outでencodingの変換はやめた
- 高速化対応
テストを追加
- kwatchのCGIAltのコードを参考にテストコードを追加した
- (標準コードを横取りしてる点が素敵)
文字コード対応
multipart form on 1.8
- 現状はマルチパートになるとIO型になっているので改良したい
- ただし互換性が1.9版で完全になくなるのは困るのでは?
- 戻り値をstringにするけれど互換性用に.readを追加してある!
- CGI#filesでアップロードされたファイルが一覧で取れる(Hash形式で入っている)
3.1.9.1のM17Nはこうなった
文字数のカウント変わった(国際化言語対応に!)
- 1.8 "牛タン".split(//u).size =>3
- 1.9 "牛タン".size =>3 "牛タン".bytesize =>9
- => StringのインスタンスがEncoding情報を持つようになった
1.9のString型
Encoding情報を持つようになった為に変わった部分
- String#encoding
- 破壊的に文字コードを変換するので注意
- String#force_encoding(encoding)
- 破壊的にEncoding情報を変換する。バイト情報は変更しないので注意
- Strind#encode(encoding)
- String#default_external
- 文字コードを指定しないでファイルを読み書きした場合等
- String#valid_encoding?
-
- バイト情報とEncoding情報が一致しているか検査
-
Encodingクラスが新設
文字列dump
- String.dumpだとEncoding情報が保存されない
- Marshl.dumpmだとEncoding情報付きで出力されるので二つの違いに注意
マジックコメント
まとめ
- Stringは常にEncoding情報を持っている事を意識
- StringをファイルやDBに保存する時はデータを保存したいのかEncodingごと保存したいのかを意識することが重要
- 日本語を使う時にはマジックコメントをつけるようにすること
4.レガシーアプリはこうやって動かせ
tDiaryは本家が1.9に対応するのでHikiを1.9対応することに転身
- euc-jpで書かれているのでそれに対応するマジックコメントを追加
- これをひたすら続ける(マジコメる!)
- そのうちEUC-JPとASCII-8BITの合体ができないってなエラーがでる
- データ受け取りの文字コードが指定されていないので新規ページができなかった
- CGI.newが無かったので気がつかなかった
- 独自マーシャルが実装されていてそこでもエラーが
- Array.to_sの挙動が1.8と1.9で変わっているために発生
- Array.joinに変更
- pstoreを拡張して独自transactionを使っていてそこでエラー
- 独自部分をコメント化して、オリジナルを使うと動作
5.まとめ
- マジコメをつける
- Encoding.default_externalを指定する
- UTF-8以外を使うときはCGI.newする時に:accsept_charsetを指定する
- それ以外の仕様違いは地道につぶしてゆく
- cgi.rbは1.9系で一応動くようになった
- M17Nでハマらないように注意しましょう
6.質問
Q.マルチパートのデータを上限無くメモリに確保するのはまずいのではないか?
A.上限値を制限出来るようにしたので無限にメモリに確保するようにはなっていないです
もう1個質問がありましたけど、メモ漏れ(ToT)