node.jsに入門してみる。2 ~基本的な機能に触れてみる編~

前回は、node.js のインストールと、HelloWorldアプリケーションの実装をやってみた。今回は、実際の開発を始める前に、開発に役立ちそうな超基本的な機能のいくつかにアクセスしてみようと思う。

HelloWorldで登場した機能

まずは、前回のHelloWorldアプリケーションの中に登場した機能のおさらいから。

console.log( val )

このメソッドは、引数に渡した val の値をコンソールに出力してくれる。文字以外の、例えば配列やオブジェクトを渡した場合にも、整形して表示してくれる。printf() や、PHPの var_dump() のように使えそう。

console.log('test');

response.writeHead(statusCd, otherHeaders);

HTTPレスポンスヘッダーを出力する。第1引数にステータスコード、第2引数にその他のヘッダーのキーと値を渡すようだ。

var http = require('http');
http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/html'});
  response.end('Hello World\n');
}).listen(80);

response.write(str), response.end(str)

HTTPレスポンスボディを出力する。
response.write(str) は、HelloWorldアプリケーションには登場しなかったが、HTTPレスポンスボディに str を出力するメソッド。response.end(str) も同様だが、こちらは同時に EOF を出力する。

var http = require('http');
http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/html'});
  response.write('Hello World\n');
  response.end();
}).listen(80);

require()

外部に実装された機能を読み込み、オブジェクトを作る。

外部化されたスクリプトの実装は下記のような雰囲気。

var value = 'ローカルの値';
exports.test = function(){
  // functionの実装
  console.log( 'TEST' );
}

これをロードして使用するには、下記のように書く。外部化された上記ソースを ext.js という名前で同階層に設置したとする。

var ext = require('./ext.js');←//インスタンス化される
ext.test();//←メソッドを実行してみている。

require() は、外部化スクリプトをインスタンス化して返す。この例ではインスタンスは ext に受け取っている。

require() がインスタンス化するオブジェクトは、外部化したスクリプト中では exports だと思えばよさそうな感じだ。メソッドやプロパティを実装するには、exports.xxxx のように扱えばよい。

デバッグで使えそうな値

__filename, __dirname

__filename は、実行したスクリプトファイルの絶対パス(PHPでいうと __FILE__)、__dirname はディレクトリの絶対パス(PHPでいうと dirname(__FILE__))を格納。

ざっと見たところ、PHP の __LINE__ に当たる機能はなさそうに見える。

その他よく使いそうな基本的な値

request.method

HTTPのメソッドを取得する。概ね、GET または POST が格納されるはず。

var http = require('http');
http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/html'});

  console.log(request.method);

  response.end();
}).listen(80);

request.url

リクエストされたURLを格納。ホスト名は含まず、パスとクエリストリングは含む。

var http = require('http');
http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/html'});

  console.log(request.url);

  response.end();
}).listen(80);

例えば次のような値が取得できる。

/index.html?a=b&c=d

この値を元にGETパラメータを取得することになるが、これについては後述。

request.headers.host

ホスト名を格納。ポート番号を指定してアクセスされた場合は、ポート番号も含む。

var http = require('http');
http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/html'});

  console.log(request.headers.host);

  response.end();
}).listen(80);

例えば、http://localhost:80/aaa/bbb.html にアクセスした場合は、次のような値が取得できる。

localhost:80

これを、http://localhost/aaa/bbb.html のようにポート番号を省略したら、ポート番号部分は含まれずに取得された。

localhost

request.headers['user-agent']

ユーザーエージェント名を格納。ブラウザ判別など行う場合に利用できる。

var http = require('http');
http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/html'});

  console.log(request.headers['user-agent']);

  response.end();
}).listen(80);

request.headers.referer

リファラ(ブラウザがひとつ前に閲覧していたURL)を格納。

var http = require('http');
http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/html'});

  console.log(request.headers.referer);

  response.end();
}).listen(80);

パラメータを受け取る

GETパラメータを取得する

GETパラメータの値は、前述のリクエストされたURL request.url をこねくり回して取得する。次のようにすると、上手いこと分解して取得できる。

var urlinfo = require('url').parse( request.url , true );
console.log( urlinfo );

アクセスしたパス request.url/testform.html?a=b&c=d だとした場合、urlinfo に返される値は下記のようになる。

{ search: '?a=b&c=d',
  query: { a: 'b', c: 'd' },
  pathname: '/testform.html',
  href: '/testform.html?a=b&c=d' }

POSTパラメータを取得する

POSTパラメータは、requestオブジェクトの dataというイベントハンドラを通じて取得するっぽいことがドキュメントから読み取れる。次の例は、dataイベントで受け取れる引数 chunk にPOSTパラメータ(リクエストボディ)が渡されてくるので、GETパラメータ取得と同様、require('url').parse() を使ってオブジェクトに格納している。

var http = require('http');
http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/html'});

  request.on( 'data' , function(chunk){
    var urlinfo = require('url').parse( '/?'+chunk.toString() , true );
    console.log( urlinfo );
  } );

  response.end();
}).listen(80);

関連するイベントハンドラに、endclose があるが、とりあえずこれはまた今度。

ちなみに、chunk は細切れにされて複数回に分割されて送信されてくるものを言う。実際には、何回かに分けて受け取り(=dataイベントが複数回発生する)、自分で結合してから扱う必要があるのかも知れない。

まとめ

概ねこれくらいを覚えておけば、基本的なウェブサーバのスクリプトを書き進めるには十分だと思う。

もうちょっといじくって、ある程度言語環境に慣れてきたら、いよいよ WebSocket に入門してみようと思う。それはまた追って。


プロフィール

ときにはデザイナ、ときにはディレクタ、ときにはプログラマ、ときには何でも屋と、ウェブの世界で未熟ながらもいろいろやっている、コヤナギトモヤです。

ツイッター上ではこのヒト。
@tomk79

RSSフィード

ページの先頭へ戻る