netモジュールとdnsモジュールを使ってtelnetからHTTPを直に叩く的なことをやってみる

前回のエントリで鬱鬱してる、とか書いておきながら「あーやっぱりサーバサイドやらないとこれから生きて行けないなー、でも基礎わからないしなー、node.jsだったらHTTPからかなー」とか考えてちょっと触ってみたらなかなか楽しかったので記事を書いてみるのです。
http://ruffnex.oc.to/kenji/xrea/http.txtを読んで、telnetからHTTPを直接叩くのと、node.jsでそれを実現するコードを書いていきます。

telnetでHTTPのGETを叩く

まあ、説明の通りなのですけど。プロンプトを開いて、以下のように入力・実行!

$ telnet sasaplus1.sakura.ne.jp 80
Trying 182.48.49.27...
Connected to sasaplus1.sakura.ne.jp.
Escape character is '^]'.
GET http://sasaplus1.sakura.ne.jp/ HTTP/1.0

HTTP/1.1 200 OK
Date: Thu, 16 Aug 2012 17:20:43 GMT
Server: Apache/1.3.42 (Unix) mod_ssl/2.8.31 OpenSSL/0.9.8e
Last-Modified: Sat, 11 Aug 2012 16:33:35 GMT
ETag: "5c8-5026895f"
Accept-Ranges: bytes
Content-Length: 1480
Connection: close
Content-Type: text/html

<!DOCTYPE html>

<!-- head -->
<meta charset="utf-8">
<meta name="Author" content="sasa+1">
<meta name="Generator" content="Vim">
<meta name="format-detection" content="telephone=no">
<meta name="viewport" content="width=device-width">
<title>chocolateorange</title>
<link href="mailto:sasaplus1&#64;gmail.com" rel="author">
<link href="/common/image/icon.png" rel="icon" type="image/png">
<link href="/common/css/i-claris.css" title="claris" media="only screen and (max-device-width:480px)" rel="stylesheet">
<link href="/common/css/claris.css" title="claris" media="screen and (min-device-width:481px)" rel="stylesheet">
<link href="//bitbucket.org/sasaplus1/chocolateorange/rss" title="chocolateorange" rel="alternate" type="application/rss+xml">

<!-- body -->
<header>
  <h1>chocolateorange</h1>
  </header>

<nav>
  <h2>links</h2>
  <dl>
    <dt>Twitter
    <dd><a href="//twitter.com/sasaplus1/">@sasaplus1</a>
    <dt>weblog
    <dd><a href="//d.hatena.ne.jp/sasaplus1/">Hatena::Diary</a>
    <dt>repositories / codes
    <dd><a href="//github.com/sasaplus1/">github</a>
    <dd><a href="//gist.github.com/sasaplus1/">gist</a></dd>
    <dd><a href="//bitbucket.org/sasaplus1/">bitbucket</a>
    <dd><a href="//jsdo.it/sasaplus1/">jsdo.it</a>
    <dd><a href="//makebooth.com/booth/sasaplus1/">makebooth</a>
  </dl>
</nav>

<footer>
  <p><small><a href="/">chocolateorange</a> &copy; 2004-2012 sasa+1</small>
</footer>

<script src="/common/js/google-analytics.js"></script>
Connection closed by foreign host.

上記で実際に入力している部分は

GET http://sasaplus1.sakura.ne.jp/ HTTP/1.0

だけ。これで応答がずらーっと表示されます。HTTPを話している感じ。

node.jsからこれを実行してみる

以下のコードを書く!

// app.js
var dns= require('dns'),
    net = require('net'),
    HOST = 'sasaplus1.sakura.ne.jp';

dns.lookup(HOST, 4, function (err, address, family) {

  var socket;

  if (err) throw err;

  socket = net.createConnection(80, String(address));

  socket.on('connect', function () {
    socket.write('GET http://' + HOST + '/ HTTP/1.0\r\n', 'utf-8');
    socket.write('\r\n', 'utf-8');
  });
  socket.on('data', function (data) {
    console.log(String(data));
  });
  socket.on('end', function () {
    socket.end();
  });
  socket.on('error', function (err) {
    console.error(err);
  });

});

んで、実行する。

$ node app.js
HTTP/1.1 200 OK^M
Date: Thu, 16 Aug 2012 17:35:15 GMT^M
Server: Apache/1.3.42 (Unix) mod_ssl/2.8.31 OpenSSL/0.9.8e^M
Last-Modified: Sat, 11 Aug 2012 16:33:35 GMT^M
ETag: "5c8-5026895f"^M
Accept-Ranges: bytes^M
Content-Length: 1480^M
Connection: close^M
Content-Type: text/html^M
^M
<!DOCTYPE html>

<!-- head -->
<meta charset="utf-8">
<meta name="Author" content="sasa+1">
<meta name="Generator" content="Vim">
<meta name="format-detection" content="telephone=no">
<meta name="viewport" content="width=device-width">
<title>chocolateorange</title>
<link href="mailto:sasaplus1&#64;gmail.com" rel="author">
<link href="/common/image/icon.png" rel="icon" type="image/png">
<link href="/common/css/i-claris.css" title="claris" media="only screen and (max-device-width:480px)" rel="stylesheet">
<link href="/common/css/claris.css" title="claris" media="screen and (min-device-width:481px)" rel="stylesheet">
<link href="//bitbucket.org/sasaplus1/chocolateorange/rss" title="chocolateorange" rel="alternate" type="application/rss+xml">

<!-- body -->
<header>
  <h1>chocolateorange</h1>
</header>

<nav>
  <h2>links</h2>
  <dl>
    <dt>Twitter
    <dd><a href="//twitter.com/sasaplus1/">@sasaplus1</a>
    <dt>weblog
    <dd><a href="//d.hatena.ne.jp/sasaplus1/">Hatena::Diary</a>
    <dt>repositories / codes
    <dd><a href="//github.com/sasaplus1/">github</a>
    <dd><a href="//gist.github.com/sasaplus1/">gist</
a></dd>
    <dd><a href="//bitbucket.org/sasaplus1/">bitbucket</a>
    <dd><a href="//jsdo.it/sasaplus1/">jsdo.it</a>
    <dd><a href="//makebooth.com/booth/sasaplus1/">makebooth</a>
  </dl>
</nav>

<footer>
  <p><small><a href="/">chocolateorange</a> &copy; 2004-2012 sasa+1</small>
</footer>

<script src="/common/js/google-analytics.js"></script>

レスポンス同じ!あ、ヘッダの辺りの^MはCRです。


というわけでHTTP面白いね!(最初の簡単な部分だからなんだろうけど)