Day 16: QURI
これは fukamachi products advent calendar 2016 の16日目の記事です。
今日はQURIについて話します。
PURIへの不満
Common LispにはURIを扱うライブラリとしてずっとPURIが使われていました。
僕も詳しい経緯は知らないのですが、元々Allegro CLにあったURIライブラリを処理系可搬にしたのがPURIのようです。元となったAllegro CLのURIライブラリはCopyrightが1998年からになっており、かなり古くからあるようですね。
古くからあり広く使われてきたからと言って、不満がないわけではありません。
最もよくある不満は、Unicode対応がないこと。PURIで、URLエンコードされているUnicode文字列をデコードすると文字化けするのです。
これだけならばURLデコードにPURIを使わなければいい、という話ですが、PURIはしかもそれをデフォルトでデコードするという意味のわからない仕様なのです。
puri-unicode
これに対して各自いくらかパッチを当てたりして使っていましたが、@archimag *1がPURIのUnicode対応版のpuri-unicodeを作ってそっとGitHubに置いていました。これが事の発端です。
するとそれを見つけた第三者が、puri-unicodeをQuicklispに入れてくれと申請を出します。
※以下は完全に意訳です。
HiTECNOLOGYs: puri-unicodeをQuicklispに入れて。
Zach: puri.asdが本家と競合するから入れられない。
それを聞いて今度は@archimagに「システム名がPURIと競合してるよ (ロシア語)」と送ります。
HiTECNOLOGYs: システム名がpuriと競合してるよ。
archimag: これはわざとだよ。puriはUnicode周りで問題がある。puriの代わりにpuri-unicodeをロードすればいい。
HiTECNOLOGYs: でもどうにかしてQuicklispに入れられないかな?
archimag: それはZachに言ってくれ。
という感じで全く話になりません。
Zach: 本家PURIにマージできたらいいと思うんだけど。
(一同): 確かに。
Andrew (Wookieの作者): メンテナにメールしてみました。返事ないです。
みたいなことを一年以上かけてやってるわけです。
通常、メンテナに連絡取れないときは新しいメンテナとなってマージしたものをQuicklispに置き換えて登録することが可能です *2。しかし出て来る人みんな非協力でどうにも進まない。まあ僕は何も手伝ってないので文句言える立場じゃないけど。
twitter.compuri使うたびにハマるし機能足りてないから新しく作るかぁ、ライブラリ名は何にしようかなぁ、Qualified URI library、略してquri (キュウリ) とかどうか、まで考えて面倒になったので誰か代わりに作っていいですよ
— fukamachi (@nitro_idiot) 2014年9月15日
こういうことを半分本気でツイートしたんだけど、冗談と思われたのか意外とfavられずにタイムラインの底に沈みました。
Wooの副産物
そんなツイートも忘れて数ヶ月後のこと。Wookieの高速化やWooの開発などに没頭していた最中。
昨日の記事でWooを高速化する過程でURIパース部分にそれなりのボトルネックがあることがわかってきました。使っているライブラリはあのPURIです。
機能だけでなく速度にも問題がある。これは単純にUnicode対応すればいいという話ではなくなってきました。そういう経緯で、やっぱり自前で高速かつ高機能なURIライブラリを作る必要があろう、と考えました。
それが「QURI (キュウリ)」です。
QURI
QURIに求められていたのは、Wooで使うので可能な限り高速であること。PURIの代替機能をすべて持つこと。それからPURIに足りない機能を補完することです。
具体的に足りなかったのは以下です。
- UTF-8対応
- userinfo対応 (
git@github.com
のgit
の部分) - IPv6対応 (
ldap://[2001:db8::7]/
など) - URLエンコーダ・デコーダ
- URIライブラリにまとめてしまうほうがわかりやすい
- 別でいくつかライブラリがあったがどれも遅い
QURIではfast-httpで得た、高速なパーサを書く知見を活かしてURIをパースしました。つまりtagbodyとgoのオンパレードです。
最終的にURIパーサとしてはPURIより6.6倍高速にできました。
例によってRedditにも投稿されて議論されていました。「きゅうりってのはキューカンバーのことだよ」とか書いてあって面白いです。
DrakmaのQURI利用騒動
もはやPURIを使うモチベーションはなくなりました。僕の立場としてはPURIを問題のあるメンテナンスのされていないプロダクトとして喧伝し、PURIを使うプロダクトを減らしていく必要がありました。けれどWooの開発もあったのでなかなか宣伝して回るのも手が足りません。まず手始めに、僕のプロダクトでPURIをQURIに置き換えたりしていました。
そんなある日、僕の知らない間にCommon Lispの代表的なHTTPクライアントのDrakmaに「PURIをQURIで置き換える」というPull Requestが来て、トントン拍子でマージされました。
これによりDrakmaはUTF-8対応できました。Drakma自体は置換がうまくいったのです。けれど、Drakmaに依存する多くのライブラリが返り値としてPURIのオブジェクトが返ってくることを期待しているコードがあるようで、Quicklispの中に多くのライブラリが影響を受けて壊れたようです。そのためこのPull Requestはやむなくrevertされました。
メンテナンスはされていても広く使われていることで必要な改善もできずに朽ちていく過程です。
ちなみに僕はこの話の4ヶ月前にDexadorという新しいHTTPライブラリも作っています。こちらはもちろんfast-httpとQURIを使っており、Drakmaを置き換える新世代のライブラリを目指したものです。
Dexadorについては20日目に詳しくお話するので楽しみにしていてください。
おわりに
QURIはGitHubで公開されており、Starは44です。
明日のアドベントカレンダーは17日目のsmart-bufferについてです。お楽しみに。
*1:Andrey, RESTASの作者。https://github.com/archimag
*2:named-readtablesでは実際にそれが起きた