情報アイランド

「情報を制する者は世界を制す」をモットーに様々な情報を提供することを目指すブログです。現在はプログラミング関連情報が多めですが、投資関連情報も取り扱っていきたいです。

httpモジュールによるHTTPサーバ(4)テキストデータの送信

この記事は「httpモジュールによるHTTPサーバ」という連載記事の4つ目の記事です。

その他の記事に関しては下を参照してください。

この記事ではhttpモジュールを使ってHTTPリクエストに対してリクエストメソッドやURLに応じて様々なテキストデータの送信を行うHTTPサーバを作成する方法を説明します。

リクエストメソッドとURL

リクエストメソッドとURLの取得方法に関しては前回の記事を参照してください。

レスポンスヘッダの設定

HTTPレスポンスヘッダのフィールドを設定するにはres.setHeader関数を使用します。

var http = require('http');

var server = http.createServer(function (req, res) {
    try {
        res.setHeader('xxx', 'yyy');
    }
    finally {
        res.end();
    }
});

第1引数にフィールド名を指定します。

第2引数にフィールドの値を指定します。

レスポンスステータスの設定

HTTPレスポンスのステータスコードはres.statusCodeに設定し、ステータスメッセージはres.statusMessageに設定します。

var server = http.createServer(function (req, res) {
    try {
        res.statusCode = 200;
        res.statusMessage = http.STATUS_CODES[200];
    }
    finally {
        res.end();
    }
});

なお、httpモジュールがサポートしている全てのステータスはhttp.STATUS_CODESにオブジェクトとして格納されています。ステータスコードがこのオブジェクトのプロパティ名となり、ステータスメッセージがプロパティの値となっています。

レスポンスの送信

resはHTTPレスポンスボディにデータを書き込むストリームでもあるため、HTTPレスポンスボディにデータを設定するにはres.write関数を使用します。

var server = http.createServer(function (req, res) {
    try {
        res.write('xxx');
    }
    finally {
        res.end();
    }
});

この関数はHTTPレスポンスの送信も行います

そのため、この関数を呼び出す前にHTTPレスポンスヘッダやステータスを設定しておかなければなりませんし、この関数を呼び出した後に設定することはできません。

レスポンスヘッダ

HTTPレスポンスとしてヘッダのみを先に送信するにはres.writeHead関数を使用します。

var server = http.createServer(function (req, res) {
    try {
        res.writeHead(200, http.STATUS_CODES[200], {
            xxx: 'yyy'
        });
    }
    finally {
        res.end();
    }
});

第1引数にステータスコードを指定します。

第2引数にステータスメッセージを指定します。この引数は指定しなくても構いません。

第3引数にヘッダをオブジェクトとして指定します。この引数は指定しなくても構いません。オブジェクトのプロパティがヘッダのフィールドを表し、プロパティ名がフィールド名を表し、プロパティの値がフィールドの値を表すようにします。

なお、この関数を呼び出す前にHTTPレスポンスステータスが設定されていた場合にはその設定は無視されます(この関数で指定されたHTTPレスポンスステータスが送信されます)。

また、この関数を呼び出す前にHTTPレスポンスヘッダが設定されていた場合には第3引数のヘッダに統合したものが送信されます。

サンプルコード1

クライアントからリクエストを受け取ったらリクエストメソッドやURLに応じて様々なテキストデータを返すHTTPサーバを作成し、起動します。

Enterキーが押されたらサーバを停止し、プログラムを終了します。

http-server-text.js

var http = require('http');
var url = require('url');

var server = http.createServer(function (req, res) {
    try {
        console.log('requested.');
        console.log('method: ' + req.method);
        console.log('url: ' + req.url);
        console.log('query: %j', url.parse(req.url, true).query);
        console.log('user agent: ' + req.headers['user-agent']);

        res.setHeader('Content-Type', 'text/plain; charset=utf-8');
        if (req.method === 'GET') {
            var text = null;
            if (req.url === '/') {
                text = 'welcome to pizyumi\'s website. this is home page.\r\n';
            }
            else if (req.url === '/author') {
                text = 'author is pizyumi.\r\n'
            }
            else if (req.url === '/hello') {
                text = 'this is hello page.\r\n';
            }
            else if (req.url.startsWith('/hello/')) {
                text = 'hello, ' + req.url.split('/')[2] + '.\r\n';
            }
            if (text) {
                res.statusCode = 200;
                res.write(text);
            }
            else {
                res.statusCode = 404;
                res.write(http.STATUS_CODES[404] + '\r\n');
            }
        }
        else if (req.method === 'POST') {
            res.statusCode = 200;
            res.write('request method is post.\r\n');
        }
        else {
            res.statusCode = 501;
            res.write(http.STATUS_CODES[501] + '\r\n');
        }
    }
    catch (err) {
        console.error('unhandled exception has occured.');
        console.error(err);
        res.setHeader('Content-Type', 'text/plain; charset=utf-8');
        res.res.statusCode = 500;
        res.write(http.STATUS_CODES[500] + '\r\n');
    }
    finally {
        res.end();
    }
});
server.listen(3000, function () {
    console.log('http server is running...press enter key to exit.');

    process.stdin.on('data', function (data) {
        if (data.indexOf('\n') !== -1) {
            server.close(function () {
                console.log('http server closed.');
                process.exit(0);
            });
        }
    });
});
server.on('error', function (err) {
    console.error(err);
    process.exit(1);
});

実行結果

実行結果の確認のためにcURLを使用しています。

コードを実行するとHTTPサーバが起動します。

C:\work\node>node http-server-text.js
http server is running...press enter key to exit.

cURLを使ってサーバに対して様々なHTTPリクエストを行います。

C:\work\node>curl -v http://localhost:3000/
*   Trying ::1...
* Connected to localhost (::1) port 3000 (#0)
> GET / HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.46.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=utf-8
< Date: Sat, 30 Jul 2016 02:39:28 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
<
welcome to pizyumi's website. this is home page.
* Connection #0 to host localhost left intact
C:\work\node>curl -v http://localhost:3000/author
*   Trying ::1...
* Connected to localhost (::1) port 3000 (#0)
> GET /author HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.46.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=utf-8
< Date: Sat, 30 Jul 2016 02:39:43 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
<
author is pizyumi.
* Connection #0 to host localhost left intact
C:\work\node>curl -v http://localhost:3000/hello
*   Trying ::1...
* Connected to localhost (::1) port 3000 (#0)
> GET /hello HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.46.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=utf-8
< Date: Sat, 30 Jul 2016 02:39:52 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
<
this is hello page.
* Connection #0 to host localhost left intact
C:\work\node>curl -v http://localhost:3000/hello/
*   Trying ::1...
* Connected to localhost (::1) port 3000 (#0)
> GET /hello/ HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.46.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=utf-8
< Date: Sat, 30 Jul 2016 02:40:01 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
<
hello, .
* Connection #0 to host localhost left intact
C:\work\node>curl -v http://localhost:3000/hello/irori
*   Trying ::1...
* Connected to localhost (::1) port 3000 (#0)
> GET /hello/irori HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.46.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=utf-8
< Date: Sat, 30 Jul 2016 02:40:07 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
<
hello, irori.
* Connection #0 to host localhost left intact
C:\work\node>curl -v http://localhost:3000/hello/irori/suki
*   Trying ::1...
* Connected to localhost (::1) port 3000 (#0)
> GET /hello/irori/suki HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.46.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=utf-8
< Date: Sat, 30 Jul 2016 02:40:14 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
<
hello, irori.
* Connection #0 to host localhost left intact
C:\work\node>curl -v http://localhost:3000/qqq
*   Trying ::1...
* Connected to localhost (::1) port 3000 (#0)
> GET /qqq HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.46.0
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Content-Type: text/plain; charset=utf-8
< Date: Sat, 30 Jul 2016 02:40:22 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
<
Not Found
* Connection #0 to host localhost left intact
C:\work\node>curl -v http://localhost:3000/ -X POST
*   Trying ::1...
* Connected to localhost (::1) port 3000 (#0)
> POST / HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.46.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/plain; charset=utf-8
< Date: Sat, 30 Jul 2016 02:40:31 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
<
request method is post.
* Connection #0 to host localhost left intact
C:\work\node>curl -v http://localhost:3000/ -X DELETE
*   Trying ::1...
* Connected to localhost (::1) port 3000 (#0)
> DELETE / HTTP/1.1
> Host: localhost:3000
> User-Agent: curl/7.46.0
> Accept: */*
>
< HTTP/1.1 501 Not Implemented
< Content-Type: text/plain; charset=utf-8
< Date: Sat, 30 Jul 2016 02:40:40 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
<
Not Implemented
* Connection #0 to host localhost left intact

サーバから正しくレスポンスが返っていることが分かります。

Enterキーを押すとサーバが停止し、プログラムが終了します。

関連

pizyumi
プログラミング歴19年のベテランプログラマー。業務システム全般何でも作れます。現在はWeb系の技術を勉強中。
スポンサーリンク

-Node.js