expressコードリーディング その1 connectを読む
使用するフレームワークのコードはちゃんと読んで理解しとけと偉い人が言ってた気がするのでexpressのコードを読んでみる。
今回読むexpressのバージョンは2.4.3。
GitHub - expressjs/express at 2.4.3: Fast, unopinionated, minimalist web framework for node.
が、その前に依存してるモジュールを読む。expressが依存してるライブラリは以下のようになっている。
"dependencies": { "connect": ">= 1.5.1 < 2.0.0", "mime": ">= 0.0.1", "qs": ">= 0.0.6" }, "devDependencies": { "connect-form": "0.2.1", "ejs": "0.4.2", "expresso": "0.7.2", "hamljs": "0.5.1", "jade": "0.11.0", "stylus": "0.13.0", "should": "0.2.1", "express-messages": "0.0.2", "node-markdown": ">= 0.0.1", "connect-redis": ">= 0.0.1" },
この中でも特に重要なのがconnectで、expressのapp.use()とかでmiddlewareを設定できるのはこのconnectの機能。なのでまずconnectを読む。connectのバージョンは1.6.0。
GitHub - senchalabs/connect at 1.6.0: Connect is a middleware layer for Node.js
まずコア機能のcreateServer。
var HTTPServer = require('./http').Server , HTTPSServer = require('./https').Server exports = module.exports = createServer; ... function createServer() { if ('object' == typeof arguments[0]) { return new HTTPSServer(arguments[0], Array.prototype.slice.call(arguments, 1)); } else { return new HTTPServer(Array.prototype.slice.call(arguments)); } };
これは第一引数がオブジェクトだったらHTTPSServer、そうじゃなかったらHTTPServerを呼んでるだけ。こういう風に使うよってコード中のExamplesに書いてあってわかりやすい。
/* * Examples: * * An example HTTP server, accepting several middleware. * * var server = connect.createServer( * connect.logger() * , connect.static(__dirname + '/public') * ); * * An HTTPS server, utilizing the same middleware as above. * * var server = connect.createServer( * { key: key, cert: cert } * , connect.logger() * , connect.static(__dirname + '/public') * ); */
最後のほうに
exports.HTTPServer = HTTPServer; exports.HTTPSServer = HTTPSServer;
って書いてあるので、直接こっち呼んでもよさそう。とりあえず重要なのはhttp.jsとhttps.jsというのがわかった。http.jsは後で読むとして続き。
同梱のmiddlewareのロードのところ。connectのmiddlewareは自由に定義して使えるのがいいところだけど、最初からよく使いそうなのとかは同梱してある。middleware/*.jsがそれら。それのロードをここでやってる。
exports.middleware = {}; fs.readdirSync(__dirname + '/middleware').forEach(function(filename){ if (/\.js$/.test(filename)) { var name = filename.substr(0, filename.lastIndexOf('.')); exports.middleware.__defineGetter__(name, function(){ return require('./middleware/' + name); }); } }); exports.utils.merge(exports, exports.middleware);
feaddirSyncでファイル名読んで__definGetter__で定義してる。これだけだとconnct.middleware.logger()とか書かないといけないから、utils.mergeでexportsにマージしてconnect.logger()とかできるようにしてる。utilsっていうのはutils.jsにあるユーティリティ関数群。connect以外でも使えそうな便利なのがいっぱい定義されてた。
今回はここまで。次はhttp.jsを読む。