1. Yohei Sasaki
  2. node.js hands-on materials

Commits

Yohei Sasaki  committed e3ec6e7

[mod] http server done.

  • Participants
  • Parent commits 8a1b153
  • Branches default

Comments (0)

Files changed (12)

File source/index.rst

View file
 
 log 2010/10/30
   絶賛作成中.
-  :doc:`intro/npm` まで完了.
+  :doc:`webapp/http_server` まで完了.
   入れてほしいコンテンツがあれば `@yssk22 <http://twitter.com/yssk22>`_ まで.
   (or bitbucket にチケット起票で)
 
    
    webapp/http_server
    webapp/websocket
-   webapp/template
    webapp/jsdom
 
 モジュール探訪

File source/webapp/.#http_server.rst

View file
+yssk22@macbook.local.8588

File source/webapp/http_server.rst

View file
 HTTP Server 
 ================================================
+
+この章ではHTTP Serverの基本的な作り方を学びます.
+
+
+Hello World
+------------------------------------------------
+
+まずはHello Worldします.
+
+.. literalinclude:: src/hello_world.js
+    :language: javascript
+    :linenos:
+
+これだけです.
+
+http.createServer(function(req, res){ /* */ }} で httpServer インスタンスを作成し,所定のポートでlistenするだけです.
+
+リクエストの処理もイベント
+-------------------------------------------------
+
+サーバーインスタンス自体がEventEmitterオブジェクトなので、次のように,リクエスト処理を分割して記述できます.
+
+.. literalinclude:: src/hello_world_with_logging.js
+    :language: javascript
+    :linenos:
+
+便利でしょう?
+
+ちなみに,
+
+::
+   
+   var server = http.createServer(function(req, res){  });
+ 
+は,以下と等価です.
+
+::
+
+   var server = http.createServer();
+   server.on('request', function(req, res){  });
+
+非同期メソッドを使う
+-------------------------------------------------
+
+リクエストの処理中に非同期イベントを発生させることは問題ありません. しかるべきタイミングで response.writeHead(), response.end() を呼び出せば正しくコンテンツを返すことができます. 
+
+.. literalinclude:: src/hello_world_with_events.js
+    :language: javascript
+    :linenos:
+
+たとえばファイルをホストする場合は次のようにできます.
+
+.. literalinclude:: src/hello_world_with_file.js
+    :language: javascript
+    :linenos:
+
+/tmp/helloworld.html にファイルを置かない場合は 500 Error になりますが,置けばそのファイルがレスポンスとして送信されます.
+
+HTTP POST を扱う
+-------------------------------------------------
+
+request イベントで渡される http.serverRequest オブジェクトは読み込み可能なストリームです.この serverRequest オブジェクトの data イベントを使うことで POST データの読み取りをすることができます.
+
+以下は簡単なEcho HTTP Serverの例です.
+
+.. literalinclude:: src/hello_world_with_post.js
+    :language: javascript
+    :linenos:
+
+
+テンプレートエンジンを使う
+-------------------------------------------------
+
+最後に,テンプレートエンジンを使ってみます. node.js はJavaScriptが動作しますから,JavaScript で実装されているものであれば何でもかまいません [#f1]_ .
+
+EJS
+++++++++++++++++++++++++++++++++++++++++++++++++++
+
+`EJS <http://embeddedjs.com/>`_ は Ruby の ERB のような実装のテンプレートエンジンです.
+
+::
+
+   $ npm install ejs
+
+これでEJSが使えるようになりますので,アプリケーションに組み込んでみます.
+
+.. literalinclude:: src/hello_world_with_ejs.js
+    :language: javascript
+    :linenos:
+
+このプログラムと同じディレクトリに template.ejs ファイルを用意します.
+
+.. literalinclude:: src/template.ejs
+    :language: html
+    :linenos:
+
+その他のテンプレートエンジン
+++++++++++++++++++++++++++++++++++++++++++++++++++
+
+筆者的には https://github.com/janl/mustache.js がお気に入りです.
+
+.. [#f1] DOMを使うものでもjsdom と呼ばれるライブラリを使えば(苦労はするものの)大抵は動きます.
+
+

File source/webapp/src/hello_world.js

View file
+var http = require('http');
+var server = http.createServer(function(req, res){
+   res.writeHead(200, {'Content-Type': 'text/plain'});
+   res.write('Hello World\n');
+   res.end();
+});
+server.listen(3000);

File source/webapp/src/hello_world_with_count.js

View file
+var http = require('http');
+
+var server = http.createServer(function(req, res){
+   res.writeHead(200, {
+      'Content-Type': 'text/plain',
+      'Connection': 'close'
+   });
+   res.write('Hello World\n');
+   res.end();
+});
+
+var i = 0;
+server.on('request', function(req, res){
+   i = i + 1;
+});
+
+
+server.listen(3000);
+
+process.on('SIGINT', function(){
+   console.log('total requests: ' + i);
+   process.exit(0);
+});

File source/webapp/src/hello_world_with_ejs.js

View file
+var http = require('http'),
+    fs = require('fs'),
+    querystring = require('querystring'),
+    ejs = require('ejs');
+
+function extractParams(url){
+   return querystring.parse(url.split('?')[1] || "");
+}
+
+var server = http.createServer(function(req, res){
+   var template = fs.readFileSync(__dirname + '/template.ejs');
+   var params = extractParams(req.url);
+   res.writeHead(200, {'Content-Type': 'text/plain'});
+   res.write(ejs.render(template.toString(),  {
+      locals: {
+         name: params.name
+      }
+   }));;
+   res.end();
+});
+server.listen(3000);

File source/webapp/src/hello_world_with_events.js

View file
+var http = require('http');
+var server = http.createServer(function(req, res){
+   setTimeout(
+      function(){
+         res.writeHead(503, {'Content-Type': 'text/plain'});
+         res.write("I'm busy\n");
+         res.end();
+      },
+      1000
+   );
+});
+server.listen(3000);

File source/webapp/src/hello_world_with_file.js

View file
+var http = require('http'),
+    fs = require('fs');
+var server = http.createServer(function(req, res){
+   var read = fs.createReadStream('/tmp/helloworld.html');
+   var head = true;
+   read.on('error', function(){
+      res.writeHead(500, {'Content-Type': 'text/plain'});
+      res.write('IO Error\n');
+      res.end();
+   });
+   read.on('data', function(data){
+      if( head ){
+         res.writeHead(200, {'Content-Type': 'text/plain'});
+         head = false;
+      }
+      res.write(data);
+   });
+   read.on('end', function(data){
+      res.end();
+   });
+});
+server.listen(3000);

File source/webapp/src/hello_world_with_logging.js

View file
+var http = require('http');
+
+var server = http.createServer(function(req, res){
+   res.writeHead(200, {
+      'Content-Type': 'text/plain'
+   });
+   res.write('Hello World\n');
+   res.end();
+});
+
+server.on('request', function(req, res){
+   console.log(req.url + ' "' + req.headers['user-agent'] + '"');
+});
+
+server.listen(3000);
+

File source/webapp/src/hello_world_with_post.js

View file
+var http = require('http');
+var server = http.createServer(function(req, res){
+   if( req.method == 'POST' ){
+      res.writeHead(200, {
+         'Content-Type': req.headers['content-type']
+      });
+      req.on('data', function(data){
+         res.write(data);
+      });
+      req.on('end', function(){
+         res.end();
+      });
+
+   }else{
+      res.writeHead(200, {'Content-Type': 'text/plain'});
+      res.write('Hello World\n');
+      res.end();
+   }
+
+});
+server.listen(3000);

File source/webapp/src/template.ejs

View file
+<html>
+  <body>
+    <p>
+      Hello <%= name %>
+    </p>
+  </body>
+</html>

File source/webapp/template.rst

-テンプレートシステムの利用
-================================================
-
-
-EJS
-------------------------------------------------