node.js/express で CouchDB をパワーアップ大作戦

CouchDB をメインのアプリケーションサーバーとして使っているものの、サーバーサイドで他のサービスと連携したいときにはちょっと不便さを感じてしまいます。

そういうときは、イマドキ?のWeb Frameworkの上で、CouchDBをデータベースとして扱えば良いんですが、CouchDB のアプリと密に連携する(一部の機能のためだけだから)ためには言語も同じにした方が良いだろう、ということで、node.js を使い始めています。

とりあえず、認証をtwitterに任せよう。

CouchDBでアプリ作った場合、ユーザーDB自体はCouchDBに保持されます。。これはちょっとやだ。CouchDBインスタンス毎にユーザー抱えるとか。。。

で、イマドキ、ということで、twitter を認証サーバーとして使うんです。OAuth ができればOKってことで。

PHPとかPythonとかRubyとかJavaとか、GAEとかあるけど、Server Side JavaScript のサンプルがねーYO! ってことで、書いてみました。

実装の中身

gist においときました。Server Side JavaScriptIEがいないから書いていて気持ちが良いですね。

gist: 524406 - GitHub

必要なのは node.js と Express です。 token 保持のセッション周りとか面倒だったので Express に頼りました。Express は Ruby の Sintra に inspire された、node.js 用 Web Framework だそうです。あと、Connect という node.js 用のミドルウェアを使います。

という感じです。実際には oauth モジュールは独立したライブラリとしてnode.jsにあるので簡単に実装できました。 このoauthライブラリは認証用URIに対して、QueryString以外に(たとえばRequest BodyにJSONを埋め込むとか)リクエストを送ることができない、という実装上の制約はあるものの、普通に使う分には問題なさそうです。

ソースコードも一通り見ましたがJavaScriptでも非常にわかりやすい。

npm モジュールを公開してみる

もう一つ。node.js には npm という Ruby の gem、Python の setuptools/pypiPerlCPANPHPの... 的なモジュールがあります。

昨今、使うばっかりじゃダメだ、と思っているので、とりあえず自分がすぐに必要だったHTMLの本文抽出ライブラリを node.js 用の JavaScript に移植して公開してみました。完全に移植できたかどうかは怪しいですが(正規表現周りがあまり注意深く見ていないです)、github は以下。

http://github.com/yssk22/extractcontent

npm の方にも登録しておいたので、その課程を記します。

まずは何より package.json

パッケージ情報は package.json というファイルに記述します。tar.gz を展開してできたディレクトリにあればよいようなので、通常 プロジェクトのルートディレクトリに奥でしょう。

http://github.com/yssk22/extractcontent/blob/master/package.json

こんな感じでライブラリの内容を書いておきます。

"main" : "./lib/extractcontent"

これが、公開するエントリポイントになるので、require('packagename') したときには、このファイルで export されているものがライブラリとして使えます。今回は extractFromUrl と extractFromText という二つの関数を extractcontent.js で export しておきました。

インストールできるか確認。

$ npm install .

これで、カレントディレクトリの package.json を読んでインストールしようとします。
npm ok ってでればOKで、一応その後で、/usr/local/lib/node/extractcontent にファイルが展開されていることを確認して、

$ node
> require('extractcontent').extractFromUrl('http://www.yssk22.info/top');

とかして確認しました。

パッケージ公開

まずはnpmのサイトにユーザー登録から。これも npm でいけます。

$ npm adduser yssk22 password yssk22@gmail.com
...
...

尚、これをやると ~/.npmrc というファイルに平文でパスワードが書かれてしまっているので、一応 chmod 600 ~/.npmrc をしておくとよいかと。

で、あとは実際にディレクトリをpublishします。

$ npm publish .

これで http://npm.mape.me/ のサイトに tgz がアップロードされます。tgz のファイル名は、ディレクトリ名.tgz になるので、わかりやすさのために、パッケージの名前と同じディレクトリ名で開発した方が良いかな、と後になって気がつきました。適当にやっていたので、l.tgz という意味不明なパッケージ名になってしまいましたと。。

公開できたら、

$ npm install extractcontent

とやって、サイトからのインストールができることを確認しましょう。

  • /usr/local/lib/node/.npm/
  • /usr/local/lib/node/

とかに、インストール済みのパッケージがはいっているのでそれらを全部消してからやることをおすすめします。

ところでテスト

JSのテスト。今まで JSpec というやつを使っていたんですが、node.js はあらゆるメソッドが非同期実行なので、テストが終わる前にメインスレッドが終了しちゃうとか、そんな感じでテストがしにくいのです。

nodeunit というモジュールがあったのでこれを使うとよいようです。テストの終了箇所を test.end() と明示的に示すことで、そこを通過するまでメインスレッドを待機させるというような構造です。

ちなみに、全部非同期ですから print デバッグはわりと無力になるので注意してください。逐一テスト書いていくしかないという。。。