libro
www.tuyano.com
初心者のための Node.jsプログラミング入門

複数ページのルーティングとフォームのPOST送信 (2/4)

作成:2013-04-27 08:42
更新:2013-04-27 08:42

■「url」オブジェクトによるURL処理

では、用意したテンプレートを使うスクリプトを作成しましょう。これは、先にスクリプトを見ながら説明をしていったほうが早いですね。

下のリスト欄にNode.jsのスクリプトを掲載しておきます。これを実行して、http://127.0.0.1:1234/ にアクセスしてみてください。content1.ejsの内容が表示されます。このページにあるリンクをクリックすると、http://127.0.0.1:1234/otherにジャンプし、content2.ejsの内容を表示します。

では、動作の確認ができたところで、スクリプトの内容を見ながら処理の仕方を説明していきましょう。


●urlのロード
var url = require('url');
URLを扱うためには、「url」というオブジェクトをロードしておきます。このurlオブジェクトは、URLの文字列をパースし、そこから必要なものを取り出す機能を提供します。


●URLのパース
var url_parts = url.parse(request.url);
リクエストがアクセスしてきたURLをパース処理します。リクエストされたURLは、requestイベントハンドラの引数に渡されるrequestオブジェクトの「url」というプロパティで得ることができます。

urlオブジェクトの「parse」は、URLの文字列を要素ごとに分割しオブジェクト化して返すものです。これで、変数url_partsにURLの要素が保管されます。それぞれの要素は生成されたオブジェクトのプロパティとして保管されており、いつでも利用できるようになります。


●各ページのデータを用意する
今回のスクリプトでは、それぞれのページのデータをroutesという変数にまとめています。これは、アクセス先のパスをキーとして用意し、そのパスで表示されるページの情報を連想配列でまとめたものを値に設定してあります。例えば、ルートである"/"の値を見てみると、
"/":{
    "title":"Main Page",
    "message":"これはサンプルのページですよ。",
    "content":content1 }
こんな具合になっていることがわかるでしょう。連想配列には、titlemessagecontentというキーが用意されており、それぞれ「タイトルテキスト」「ページに表示するメッセージテキスト」「表示するページの内容(テンプレートデータ)」を値として保管してあります。この変数routesから、アクセスするアドレスのパスごとに必要な情報を取り出し処理しよう、というわけです。


●パスが得られない場合の処理
if (routes[url_parts.pathname] == null){……}
変数url_partsにURLの各要素がオブジェクトとして保管されていましたが、この中で「パス」の値は「pathname」というプロパティとして保管されています。

変数routesには、既に述べたように各パスごとで必要となる情報が、パスをキーとした連想配列にまとめられていました。ということは、routes[url_parts.pathname]の値を取り出せば、現在のリクエストがアクセスしているパスの情報が取り出せることになります。もしこの値がnullならば、変数routesは情報がない、すなわち「そのパスにはアクセスできない」ということになるわけです。

そこで、nullの場合にはエラーメッセージなどを表示させておきます。これで、用意されていないアドレスへの対応ができました。


●アクセスしたパスのページをレンダリングする
var content = ejs.render( template,
    {
        title: routes[url_parts.pathname].title,
        content: ejs.render(
            routes[url_parts.pathname].content,
            {
                message: routes[url_parts.pathname].message
            }
        )
    }
);
後は、変数routesから必要な値を取り出してレンダリングをするだけです。例えば、titleに設定する値は、
title: routes[url_parts.pathname].title
このように用意すればいいですし、コンテンツのレンダリングをcontentに用意するには、
content: ejs.render( 
    routes[url_parts.pathname].content, ……)
このようにすればよいでしょう。ここで表示するコンテンツのテンプレートはroutes[url_parts.pathname].contentで得られますから、これをrenderするだけです。

後は、writeHeadwriteendのセットを実行してページ出力の完了です。テンプレートのレンダリング処理があるのでちょっと面倒に見えますが、基本的に「ページで使う値はroutes[url_parts.pathname]の中にまとめられている」ということさえわかっていれば難しいことはありません。

※プログラムリストが表示されない場合

AddBlockなどの広告ブロックツールがONになっていると、プログラムリスト等が表示されない場合があります。これらのツールをOFFにしてみてください。

●プログラム・リスト●

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

var template = fs.readFileSync('./template.ejs', 'utf8');
var content1 = fs.readFileSync('./content1.ejs', 'utf8');
var content2 = fs.readFileSync('./content2.ejs', 'utf8');

var routes = {
    "/":{
        "title":"Main Page",
        "message":"これはサンプルのページですよ。",
        "content":content1},
    "/index":{
        "title":"Main Page",
        "message":"これはサンプルのページですよ。",
        "content":content1},
    "/other":{
        "title":"Other Page",
        "message":"別のページを表示していますよ。",
        "content":content2}
};

var server = http.createServer();
server.on('request', doRequest);
server.listen(1234);
console.log('Server running!');

// リクエストの処理
function doRequest(request, response) {
    var url_parts = url.parse(request.url);
    // route check
    if (routes[url_parts.pathname] == null){
        console.log("NOT FOUND PAGE:" + request.url);
        response.writeHead(200, { 'Content-Type': 'text/html' });
        response.end("<html><body><h1>NOT FOUND PAGE:" + 
            request.url + "</h1></body></html>");
        return;
    }
    // page render 
    var content = ejs.render( template,
        {
            title: routes[url_parts.pathname].title,
            content: ejs.render(
                routes[url_parts.pathname].content,
                {
                    message: routes[url_parts.pathname].message
                }
            )
        }
    );
    response.writeHead(200, {'Content-Type': 'text/html'});
    response.write(content);
    response.end();
}

※関連コンテンツ

「初心者のための Node.jsプログラミング入門」に戻る