github地址
const connect = require('connect');
const servestatic = require('serve-static');
const app = connect();
app.use(servestatic(__dirname+"/public"));
app.listen(3000);
const fs = require('fs');
const path = require('path');
const http = require('http');
const url = require('url');
const zlib = require('zlib');
class StaticServer {
constructor(config = {}) {
config = Object.assign({
defaultDir: '/',
defaultFile: 'index.html',
fileMatch: /^(gif|png|jpg|js|css)$/ig,
zipMatch: /css|js|html/ig,
maxAge: 60 * 60
}, config)
this.defaultDir = config.defaultDir;
this.defaultFile = config.defaultFile;
this.fileMatch = config.fileMatch;
this.maxAge = config.maxAge;
this.zipMatch = config.zipMatch;
}
init(server) {
const self = this;
server.on('listening', function () {
const port = server.address().port;
console.log('Server running at ' + port);
})
server.on('request', function (req, res) {
const oURL = url.parse(req.url);
const pathName = path.join(self.defaultDir, oURL.pathname.slice(1));
self.route(pathName, req, res);
});
}
route(pathName, req, res) {
const self = this;
fs.stat(pathName, function (err, stats) {
if (err) {
res.writeHead(404, "Not Found", { 'Content-Type': 'text/plain' });
res.write("This request URL " + pathName + " was not found on this server.");
res.end();
} else {
if (stats.isDirectory()) {
pathName = path.join(pathName, '/', self.defaultFile);
self.route(pathName, req, res);
} else {
const method = req.method
let type = path.extname(pathName), params = '';
type = type ? type.slice(1) : 'unknown';
if (method == 'GET') {
pathName.slice(-1) === '/' && (pathName = path.join(pathName, '/', self.defaultFile));
params = url.parse(req.url, true).query;
self.responseFile(pathName, req, res, type, params, stats);
} else if (method == 'POST') {
var _postData = "", _postMap = "";
req.on('data', function (chunk) {
_postData += chunk;
}).on("end", function () {
params = require('querystring').parse(_postData);
self.responseFile(pathName, req, res, type, params, stats);
});
} else {
self.responseFile(pathName, req, res, ext, params, stats);
}
}
}
});
}
responseFile(pathName, req, res, type, params, stat) {
const self = this;
let raw;
res.setHeader("Server", "Node/V8");
res.setHeader('Accept-Ranges', 'bytes');
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Content-Type", self._getMIME(type));
if (type.match(self.fileMatch)) {
var expires = new Date();
expires.setTime(expires.getTime() + self.maxAge * 1000);
res.setHeader('Expires', expires.toUTCString());
res.setHeader('Cache-Control', 'max-age=' + self.maxAge);
}
var lastModified = stat.mtime.toUTCString();
res.setHeader('Last-Modified', lastModified);
var ifModifiedSince = "if-modified-since";
if (req.headers[ifModifiedSince] && lastModified == req.headers[ifModifiedSince]) {
res.writeHead(304, 'Not Modified');
res.end();
return;
}
var compressHandle = function (raw, statusCode, msg) {
var stream = raw;
var acceptEncoding = req.headers['accept-encoding'] || "";
var zipMatch = type.match(self.zipMatch);
if (zipMatch && acceptEncoding.match(/\bgzip\b/)) {
res.setHeader("Content-Encoding", "gzip");
stream = raw.pipe(zlib.createGzip());
} else if (zipMatch && acceptEncoding.match(/\bdeflate\b/)) {
res.setHeader("Content-Encoding", "deflate");
stream = raw.pipe(zlib.createDeflate());
}
res.writeHead(statusCode, msg);
stream.pipe(res);
}
if (req.headers['range']) {
var range = self._getRange(req.headers['range'], stat.size);
if (range) {
res.setHeader('Content-Range', 'bytes ' + range.start + '-' + range.end + '/' + stat.size);
res.setHeader('Content-Length', range.end - range.start + 1);
raw = fs.createReadStream(pathName, { "start": range.start, "end": range.end });
compressHandle(raw, 206, 'Partial Content');
} else {
res.removeHeader('Content-Length');
res.writeHeader(416, 'Request Range Not Satisfiable');
res.end();
}
} else {
raw = fs.createReadStream(pathName);
if (type == 'json' && params.delay) {
setTimeout(function () {
compressHandle(raw, 200, 'OK');
}, params.delay);
} else {
compressHandle(raw, 200, 'OK');
}
}
}
_getMIME(type) {
var types = {
"css": "text/css",
"gif": "image/gif",
"html": "text/html",
"ico": "image/x-icon",
"jpeg": "image/jpeg",
"jpg": "image/jpeg",
"js": "text/javascript",
"json": "application/json",
"pdf": "application/pdf",
"png": "image/png",
"svg": "image/svg+xml",
"swf": "application/x-shockwave-flash",
"tiff": "image/tiff",
"txt": "text/plain",
"wav": "audio/x-wav",
"wma": "audio/x-ms-wma",
"wmv": "video/x-ms-wmv",
"xml": "text/xml"
};
return types[type] || 'application/octet-stream';
}
_getRange(str, size) {
if (str.indexOf(",") != -1) {
return;
}
var range = str.split("-"),
start = parseInt(range[0], 10),
end = parseInt(range[1], 10);
if (isNaN(start)) {
start = size - end;
end = size - 1;
} else if (isNaN(end)) {
end = size - 1;
}
if (isNaN(start) || isNaN(end) || start > end || end > size) {
return;
}
return { start: start, end: end };
}
}
const staticServer = new StaticServer({ defaultDir: __dirname })
staticServer.init(
http.createServer().listen(3000)
)