171 lines
5.7 KiB
JavaScript
171 lines
5.7 KiB
JavaScript
|
"use strict";
|
||
|
|
||
|
var fs = require("fs");
|
||
|
var http = require("http");
|
||
|
var path = require("path");
|
||
|
var querystring = require("querystring");
|
||
|
var stream = require("stream");
|
||
|
var util = require("util");
|
||
|
var url = require("url");
|
||
|
|
||
|
var mime = require("./mime")();
|
||
|
|
||
|
var Server = function Server(cwd, middlewares) {
|
||
|
if (!(this instanceof Server)) {
|
||
|
return new Server(cwd, middlewares);
|
||
|
}
|
||
|
if (!cwd) {
|
||
|
cwd = process.cwd();
|
||
|
}
|
||
|
if (typeof middlewares === "function") {
|
||
|
middlewares = [middlewares];
|
||
|
} else if (!Array.isArray(middlewares)) {
|
||
|
middlewares = [];
|
||
|
}
|
||
|
|
||
|
http.Server.call(this);
|
||
|
|
||
|
this.cwd = cwd;
|
||
|
this.middlewares = middlewares;
|
||
|
|
||
|
var requestHandler = this.handler.bind(this);
|
||
|
this.on("request", requestHandler);
|
||
|
this.once("close", function () {
|
||
|
this.removeListener("request", requestHandler);
|
||
|
});
|
||
|
};
|
||
|
util.inherits(Server, http.Server);
|
||
|
|
||
|
Server.prototype.handler = function (req, res) {
|
||
|
|
||
|
var pathname = url.parse(req.url).pathname;
|
||
|
var filename = path.join(this.cwd, path.normalize(querystring.unescape(pathname)));
|
||
|
|
||
|
var that = this;
|
||
|
fs.exists(filename, function (exists) {
|
||
|
if (exists) {
|
||
|
fs.stat(filename, function (err, stats) {
|
||
|
if (err) {
|
||
|
return that.notFound(res);
|
||
|
}
|
||
|
if (stats.isFile()) {
|
||
|
var ext = path.extname(filename);
|
||
|
var mimeType = mime(ext);
|
||
|
res.writeHead(200, {
|
||
|
"Content-Type": mimeType,
|
||
|
"Access-Control-Allow-Origin": "*"
|
||
|
});
|
||
|
fs.createReadStream(filename).pipe(res);
|
||
|
} else if (stats.isDirectory()) {
|
||
|
if (!/\/$/.test(pathname)) {
|
||
|
res.writeHead(301, {
|
||
|
"Location": path.join(pathname, "/")
|
||
|
});
|
||
|
res.end();
|
||
|
return;
|
||
|
}
|
||
|
fs.readdir(filename, function (err, files) {
|
||
|
if (err) {
|
||
|
return that.notFound(res);
|
||
|
}
|
||
|
|
||
|
var len = files.length;
|
||
|
if (!len) {
|
||
|
dir(files);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
var items = [];
|
||
|
|
||
|
files.forEach(function (file) {
|
||
|
fs.stat(path.join(filename, file), function (err, stats) {
|
||
|
if (!err) {
|
||
|
items.push(stats.isDirectory() ? path.join(file, "/") : file);
|
||
|
}
|
||
|
--len;
|
||
|
if (!len) {
|
||
|
dir(items);
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
|
||
|
function dir(files) {
|
||
|
res.writeHead(200, {
|
||
|
"Content-Type": "text/html",
|
||
|
"Access-Control-Allow-Origin": "*"
|
||
|
});
|
||
|
res.end(["",
|
||
|
'<!DOCTYPE html>',
|
||
|
'<html>',
|
||
|
' <head>',
|
||
|
' <meta charset="UTF-8">',
|
||
|
' <meta name="viewport" content="width=device-width, initial-scale=1.0">',
|
||
|
' <title>Index of ' + pathname + '</title>',
|
||
|
' </head>',
|
||
|
' <body>',
|
||
|
' <h1>Index of ' + pathname + '</h1>',
|
||
|
' <hr>',
|
||
|
' <ul>',
|
||
|
' <li><a href="..">../</a></li>',
|
||
|
files.map(function (file) {
|
||
|
return ' <li><a href="' + path.join(pathname, file) + '">' + file + '</a></li>';
|
||
|
}).join("\n"),
|
||
|
' </ul>',
|
||
|
' <hr>',
|
||
|
' </body>',
|
||
|
'</html>',
|
||
|
""].join("\n"));
|
||
|
}
|
||
|
});
|
||
|
|
||
|
} else {
|
||
|
that.notFound(res);
|
||
|
}
|
||
|
});
|
||
|
} else {
|
||
|
that.notFound(res);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
};
|
||
|
Server.prototype.notFound = function (res) {
|
||
|
res.writeHead(404, {
|
||
|
"Content-Type": "text/html",
|
||
|
"Access-Control-Allow-Origin": "*"
|
||
|
});
|
||
|
|
||
|
var file = path.join(this.cwd, "404.html");
|
||
|
fs.exists(file, function (exists) {
|
||
|
if (exists) {
|
||
|
fs.createReadStream(file).pipe(res);
|
||
|
} else {
|
||
|
default404Reader().pipe(res);
|
||
|
}
|
||
|
});
|
||
|
|
||
|
function default404Reader() {
|
||
|
var f404 = new stream.Readable();
|
||
|
f404._read = function () {
|
||
|
|
||
|
this.push(["",
|
||
|
'<!DOCTYPE html>',
|
||
|
'<html>',
|
||
|
' <head>',
|
||
|
' <meta charset="UTF-8">',
|
||
|
' <title>Not Found!</title>',
|
||
|
' </head>',
|
||
|
' <body>',
|
||
|
' <h1>File Not Found!</h1>',
|
||
|
' </body>',
|
||
|
'</html>',
|
||
|
""].join("\n"));
|
||
|
this.push(null);
|
||
|
|
||
|
};
|
||
|
return f404;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
module.exports = Server;
|