[Node.js] Webサーハ゛を作る。(2)が古くなったんで書き直してみた。clusterとmimeモジュールも使うようになってる。
説明はソースのコメントにしておいたので省略(^^;)
import * as http from "http";
import * as cluster from "cluster"; // (1)
import * as os from "os";
import * as url from "url";
import * as path from "path";
import * as querystring from "querystring";
import * as fs from "fs";
import * as mime from "mime";
const port = 8080; // 待ち受けポート番号
const contentsDir = "www"; // コンテンツフォルダ
const defaultHtml = "index.html"; // ファイル名が省略された場合(ディレクトリを指定された場合)
// 読み込むファイル名
// コンテンツフォルダのフルパスを生成
const wwwRoot = path.join(__dirname, contentsDir);
console.log("wwwRoot=" + wwwRoot);
// コア数取得
const numCPUs = os.cpus().length;
if(cluster.isMaster) { // マスターなら
// CPUコア数のワーカーを起動 (2)
for(let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on("exit", (worker, code, signal)=>{
console.log(`worker ${worker.process.pid} died`);
});
} else {
// サーバ起動
const server = http.createServer((req, res)=>{
console.dir(req.headers);
const reqUrl = url.parse(<string>req.url, true);
const contentsFile = path.join(wwwRoot, querystring.unescape(<string>reqUrl.pathname));
// ファイルの情報を取得する。そして、コールバック関数でファイルやエラーをクライアントに返す。
fs.stat(contentsFile, (err, stats)=>{
if(err) { // エラーなら、404エラーをクライアントに返す。
console.log(err);
responseError404(res);
return;
} else {
responseContent(contentsFile, stats, res);
}
});
})
.listen(port);
}
// ファイルを返す。
function responseContent(contentsFile:string, stats:fs.Stats, res:http.ServerResponse) {
if(stats.isDirectory()) { // ディレクトリなら、defaultHtml(index.html)を追加して
// fs.statを呼ぶ。
const indexFile = path.join(contentsFile, defaultHtml);
fs.stat(indexFile, (err, stats)=>{
if(err) { // エラーなら、404エラーをクライアントに返す。
console.log(err);
responseError404(res);
return;
} else {
responseContent(indexFile, stats, res);
}
});
return;
} else if(stats.isFile()) { // ファイルなら、ファイルを返す。
// 拡張子からMIMEタイプを取得してヘッダに設定する。
const extname = path.extname(contentsFile).toLocaleLowerCase();
const mimeType = mime.lookup(extname);
// レスポンスヘッダを設定
responseSetHeader(res, 200, mimeType, stats.mtime);
// ファイルのストリームを作って、クライアントに返す。
// pipe()でresにデータを流すようにする。
// resはWritableインターフェイスが実装されているのでpipe()に渡すことができる。
fs.createReadStream(contentsFile)
.pipe(res);
} else { // ファイルでもディレクトリでもないなら
// ファイルがなかったことにする。(404エラーをクライアントに返す)
responseError404(res);
}
}
// 404エラーをクライアントに返す。
function responseError404(res:http.ServerResponse):void {
res.writeHead(404, { "Content-Type":"text/plain" });
res.write("404 Not Found.\n");
res.end();
}
// レスポンスヘッダを設定
function responseSetHeader(res:http.ServerResponse, statusCode:number, mimeType:string | null,
lastModified:Date, nocache:boolean=false):void {
if(mimeType) {
res.setHeader("Content-Type", mimeType);
}
if(nocache) {
res.setHeader("Pragma", "no-cache");
res.setHeader("Cache-Control", "private, no-store, no-cache, must-revalidate");
res.setHeader("Expires", new Date().toUTCString());
}
res.setHeader("Last-Modified", lastModified.toUTCString());
res.statusCode = statusCode;
}
コメント