標準モジュールでHTTPサーバ的な

node.jsの標準モジュールだけでHTTPサーバ的なものを書いてみた。
コードは以下。だいぶ読み難いコードだけど……

#!/usr/bin/env node

// app.js

var fs = require('fs'),
    http = require('http'),
    path = require('path'),
    url = require('url'),
    server = http.createServer();

server.on('request', function (req, res) {

  var parsedUrl = url.parse(req.url);

  if (/\/$/.test(parsedUrl.pathname)) {
    parsedUrl.pathname += '/index.html';
  }

  var localPath = path.join(__dirname, parsedUrl.pathname);

  fs.exists(localPath, function (exists) {

    if (exists) {

      fs.stat(localPath, function (err, stats) {
        if (err) throw err;

        if (stats.isDirectory()) {
          res.writeHead(404, {
            'Content-Type': 'text/plain'
          });
          res.end('404 Not Found');
          return;
        }

        fs.readFile(localPath, function (err, data) {
          if (err) {
            res.writeHead(500, {
              'Content-Type': 'text/plain'
            });
            res.end('500 Internal Server Error');
            console.error(err);
            //throw err;
          }
          res.writeHead(200, {
            'Content-Type': 'text/html'
          });
          res.end(data);
        });
      });

    } else {
      res.writeHead(404, {
        'Content-Type': 'text/plain'
      });
      res.end('404 Not Found');
    }

  });

});
server.listen(process.env.PORT || 3000);
  var parsedUrl = url.parse(req.url);

  if (/\/$/.test(parsedUrl.pathname)) {
    parsedUrl.pathname += '/index.html';
  }

この部分は末尾が/で終わっていたらindex.htmlにする。(普通は301返したりするのかなあ?)
他の部分はコードを読めばわかるかと。コールバック地獄でちょっと読み難いけど。


このコードを実行して、同じディレクトリにファイルを置いたりしてあげると、
ブラウザからファイルが普通に見れます。
難点としてはファイルが存在した場合に常にtext/htmlで返すことかw
あと普通にapp.jsが見れちゃうところとかw
publicとかってディレクトリ以下しか見れない風にするとか、そもそもディレクトリを別のところにするとか、そういうことしないと駄目かなー。
あとこれ、ディレクトリトラバーサル普通にできちゃうんじゃないのとか、基本的なところがちょっとあれかも。


まー、もっと面白いのはhttpとかを使わないで作るともっと面白いんだろうと思う。
でも基本を知るくらいなら十分実用的……かな?


参考:
http://b.n-at.me/archives/407


追記:
すごい、ディレクトリトラバーサル出来ないようになってるぽい。さすが。