Node.jsで遊んだ (2)
- 2013/10/12
- Raspberry Pi
どもどもー
前回書いたコードにとんでもない問題があったんで修正したメモです。
興味ある人だけ続きをどうぞ。
とりあえず前回書いたコードを見なおしてほしい。
/*
main.js
*/
--- 略 ---
// httpリクエストが来た時の動作
function handler (req, res) {
// index.htmlを読み込んで
fs.readFile('index.html', function (err, data) {
if(err) {
// 無かったら404
}
// 表示する
res.writeHead(200);
res.write(data);
res.end();
});
}
--- 略 ---
さて、これの何が問題かといいますと、例えばTwitterBootstrapを使ったhtmlを表示させようとしてみます。
すると・・・
こうなります。
理由は簡単です。このサーバーは「どんなリクエストに対してもindex.htmlを返す」仕様です。
外部のcssやjs、画像まで。読み込もうとしたファイルはすべてindex.htmlになりますw
さすがにこれでは使い物にならないので修正しました。
/*
main.js
*/
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
, mime= require('mime')
app.listen(3000);
function handler (req, res) {
// Check File Path
var path;
if(req.url == '/') {
path = './index.html';
}
else {
path = '.' + req.url;
}
// Read File and Write
fs.readFile(path, function (err, data) {
if(err) {
res.writeHead(404, {"Content-Type": "text/plain"});
return res.end(req.url + ' not found.');
}
var type = mime.lookup(path);
res.writeHead(200, {"Content-Type": type});
res.write(data);
res.end();
});
}
各部分ごとの解説をしていきます。
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
, mime= require('mime')
app.listen(3000);
サーバーの作成、必要なモジュールのロード、及びサーバーのポート設定等を行っている部分です。
- socket.io:Socket.IO通信を使うためのモジュール
- fs:ファイル読み込みなどのファイルシステム操作モジュール
- mime:ファイルタイプ判断(後述)のためのモジュール
app.listen(3000);はサーバーのポート設定。今回は3000番ポートです。
function handler (req, res) {
// Check File Path
var path;
if(req.url == '/') {
path = './index.html';
}
else {
path = '.' + req.url;
}
ここから、リクエストに対する動作の部分になります。
ここではファイルパスの判断を行っています。
まず、req.urlはアクセスされたURLを取得取得するものです。http://hoge.com/fuga/myon.htmlへのアクセスがあった時、req.urlを使うと/fuga/myon.htmlという文字列を取得することができます。
/、つまり何もファイルを指定されなかったらindex.htmlを、そうでなかったら指定されたファイルパスを変数pathに代入しています。
ドキュメントルートはmain.jsと同じディレクトリなので、./filenameのように相対パスで設定しています。
// Read File and Write
fs.readFile(path, function (err, data) {
if(err) {
res.writeHead(404, {"Content-Type": "text/plain"});
return res.end(req.url + ' not found.');
}
ファイルの読み込みをおこない、見つからなかった時(他の要因も考えられるけど)の動作です。
fs.readFileで先ほどのpathに代入されたファイルを読み込み、エラーだったら「○○ not found.」と表示させています。
var type = mime.lookup(path);
res.writeHead(200, {"Content-Type": type});
res.write(data);
res.end();
});
}
ファイルが存在していた時の動作です。ここで注目するのがvar type = mime.lookup(path);です。
pathにより様々なファイルが読み込めるようになったわけですが、Content-Typeを区別してやらないといけないようです。
そこでmimeというモジュールをnpmでインストール、先頭にmime= require('mime')と記述して、mime.lookup(ファイルパス);でContent-Typeを判断できるようです。
ここでは変数typeにContent-Typeを代入し、res.writeHead(200, {"Content-Type": type});というようにしてContent-Typeを指定して出力しています。
現在作成しているラジコンのコントロールページはほぼ完成といった感じです。
あとはRasPiで動かして、またピン制御等のコードを追加するだけです。
さーて、SDはの修理が終わるまでにAVRでのPWM制御をマスターせねば。
ではでは〜