Help us understand the problem. What is going on with this article?

node.js 超入門②webサーバを作る(ルーティングもやってみる)

More than 1 year has passed since last update.

前回は、簡単なwebサーバを作ってみました。
今回はよりwebサーバっぽく、リクエストによって処理を分けたり、
HTMLを表示させたりしてみましょう。

(基礎知識)ファイルを分割する

node.jsでは、1つのファイルに様々な処理をつらつらと書いていく事も可能ですが、
実際に処理を書いていくと、ファイルを分けて行きたくなると思います。

その時、外部ファイルに切り出した情報をどうやって使うのかを知っておきましょう。

node.jsでは、デフォルトでexportsという機能が備わっているのでそれを使ってみます。
前回作ったwebサーバで、共通化出来そうな部分として、port番号だけ外のファイルに切り出してみます。

config.js
exports.port = 3000;

このように、exportsを使うと、portという変数を呼び出し元から使えるようになります。

使う為には3ステップです。

  • 1. 外部ファイルに使いたい変数を、exports.{変数名} = xxxと定義する
  • 2. 呼び出し元で、var hoge = require('./xxxx')と呼び出す
  • 3. hoge.{変数名}で外部ファイルの値を使う

では、server.jsから使ってみましょう。

server.js
// nodeのコアモジュールのhttpを使う
var http = require('http');
var config = require('./config');
var server = http.createServer();

server.on('request', function(req, res) {
    res.writeHead(200, {'Content-Type' : 'text/plain'});
    res.write('hello world');
    res.end();
});

// サーバを待ち受け状態にする
// 第1引数: ポート番号
// 第2引数: IPアドレス
server.listen(config.port);

console.log(config.port);
$ node server.js
ポート番号: 3000

読み込めてますね。
このようにexportsはかなり使っていくと思うので覚えておきましょう。

リクエストのURL毎に処理を分けてみる

処理されたリクエストURLは、requrlに入ってますので、実際に見てみましょう。
前回hello worldとしていた部分を、どのURLから来たかに変えてみます。

server.js
// nodeのコアモジュールのhttpを使う
var http = require('http');
var config = require('./config');
var server = http.createServer();

server.on('request', function(req, res) {
    res.writeHead(200, {'Content-Type' : 'text/plain'});
    res.write('request from: ' + req.url);
    res.end();
});

// サーバを待ち受け状態にする
// 第1引数: ポート番号
// 第2引数: IPアドレス
server.listen(config.port);

console.log('ポート番号: ' + config.port);

hoge.htmlにアクセスしてみる

スクリーンショット 2017-09-09 12.02.39.png

hoge.html?fuga=fooにアクセスしてみる

スクリーンショット 2017-09-09 12.02.34.png

リクエストURLが取れているのが分かりました。

リクエスト毎に処理を分けてみる

req.urlにリクエストのURLが入っているのが分かったので、これを使って処理を分けてみます。

/about/companyで来たときにそれぞれ別のメッセージをだして、
それ以外のリクエストだった場合は、page not foundと表示してみます。

// nodeのコアモジュールのhttpを使う
var http = require('http');
var config = require('./config');
var server = http.createServer();
var msg;

server.on('request', function(req, res) {
    res.writeHead(200, {'Content-Type' : 'text/plain'});

    // リクエストされた処理により表示内容を分けてみる
    switch (req.url) {
        case '/about':
            msg = 'welcome about page';
            break;
        case '/company':
            msg = 'welcome my company page';
            break;
        default:
            msg = 'page not found';
            break;
    }
    res.write(msg);
    res.end();
});

// サーバを待ち受け状態にする
// 第1引数: ポート番号
// 第2引数: IPアドレス
server.listen(config.port);

/aboutにアクセス

スクリーンショット 2017-09-09 12.07.17.png

/companyにアクセス

スクリーンショット 2017-09-09 12.07.24.png

それ以外のページにアクセス

スクリーンショット 2017-09-09 12.07.31.png

リクエスト毎に表示させるメッセージを変える事が出来ました

HTMLを表示してみる

HTMLを読み込む場合には、filesystemが必要になってきます。
nodeの場合、fsというモジュールがデフォルトで備わっているのでこれを使っていきます。

また、ファイルの読み込みというのは時間がかかる処理なので、前回のノンブロッキングな処理を参考に、callbackを使うようにしてみましょう。

server.js
// nodeのコアモジュールのhttpを使う
var http = require('http');
var fs     = require('fs');
var config = require('./config');
var server = http.createServer();
var msg;

server.on('request', function(req, res) {
    // ファイルを読み込む処理は時間がかかるので、callbackにして、ノンブロッキング処理にする
    fs.readFile(__dirname + '/hello.html', 'utf-8', function (err, data) {
        // エラー発生時
        if (err) {
            res.writeHead(404, {'Content-Type' : 'text/plain'});
            res.write('page not found');
            // returnを使って、ここで処理を終了させる
            return res.end();
        }

        // 表示させるのはtextじゃなくて、htmlなので、text/htmlにする
        res.writeHead(200, {'Content-Type' : 'text/html'});
        res.write(data);
        res.end();
    });
});

// サーバを待ち受け状態にする
// 第1引数: ポート番号
// 第2引数: IPアドレス
server.listen(config.port);

スクリーンショット 2017-09-09 12.16.28.png

うまく表示できました。
一応失敗してる場合も見てみたいので、読み込むファイル名をわざと間違えてhellow.jsにしてみましょう。

スクリーンショット 2017-09-09 12.19.37.png

ちゃんとpage not foundが表示されました。

まとめ

今回出来るようになった事をまとめておきましょう。

  • 外部ファイルの使うときは、exportsを使う
  • リクエストURLは、req.urlに入っているのが分かり、リクエストによって処理を分ける方法がわかった
  • HTMLファイルを読み込んで表示する事が出来た
    • その場合はデフォルトモジュールのfsを使う
    • ファイル読み込みなどの時間のかかる処理はコールバック関数にした
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away