初步实现 apache 功能
var http = require('http');
var fs = require('fs');
// 任意目录地址
var wwwDir = 'E:/desk/my-pro/QD-practice/node/2/www';
// 1. 创建 Server
var server = http.createServer();
// 2. 监听 Server 的 request 请求事件,设置请求处理函数
// 请求
// 处理
// 响应
// 一个请求对应一个响应,如果在一个请求的过程中,已经结束响应了,
// 则不能重复发送响应。
// 没有请求就没有响应。
// 以前使用过 apache 服务器软件,默认有个 www 目录,
// 所有存放在里面的内容都可以用网址访问
server.on('request', function (req, res) {
var url = req.url;
if (url === '/') {
fs.readFile(wwwDir + '/index.html', function (err, data) {
// if (err) {
// res.end('404 not found');
// } else {
//
// }
if (err) {
// return 有两个作用
// 1. 方法返回值
// 2. 阻止代码继续执行
return res.end('404 not found');
}
res.end(data);
})
} else if (url === '/boy.html') {
fs.readFile(wwwDir + '/boy.html', function (err, data) {
if (err) {
return res.end('404 not found');
}
res.end(data);
})
} else if (url === '/plus/login.html') {
fs.readFile(wwwDir + '/plus/login.html', function (err, data) {
if (err) {
return res.end('404 not found');
}
res.end(data);
})
}
});
// 3. 绑定端口号,启动服务
server.listen(3000, function () {
console.log('running...');
});
升级 apache
可以发现上面那个每新打开一个文件都要添加一个 if…else 非常麻烦,所以
var http = require('http');
var fs = require('fs');
// 任意目录地址
var wwwDir = 'E:/desk/my-pro/QD-practice/node/2';
// 1. 创建 Server
var server = http.createServer();
// 2. 监听 Server 的 request 请求事件,设置请求处理函数
server.on('request', function (req, res) {
var url = req.url;
var filePath = 'index.html';
if (url !== '/') {
filePath = url;
}
fs.readFile(wwwDir + filePath, function (err, data) {
if (err) {
// return res.end(wwwDir + filePath);
// E:/desk/my-pro/QD-practice/node/2/plus/login.html
return res.end('404 not found');
}
res.end(data);
});
});
// 3. 绑定端口号,启动服务
server.listen(3000, function () {
console.log('running...');
});
Apache 目录列表
var http = require('http');
var fs = require('fs');
var wwwDir = 'E:/desk/my-pro/QD-practice/node/2';
// 1. 创建 Server
var server = http.createServer();
// 2. 监听 Server 的 request 请求事件,设置请求处理函数
server.on('request', function (req, res) {
var url = req.url;
fs.readFile(wwwDir + '/template/template.html', function (err, data) {
if (err) {
// return res.end('404 not found');
return res.end(wwwDir + '/template/template.html');
}
// 1. 得到 wwwDir 目录列表中的文件名和目录名
// fs.readdir
// 2. 将得到的文件名和目录名替换到 template.html 中
// 2.1 在 template.html 中需要替换的位置预留一个特殊标记(随意)
// 2.2 根据 files 生成需要的 HTML 内容
// 模板引擎
fs.readdir(wwwDir + '/www', function (err, files) {
if (err) {
return res.end('Can not find www dir')
}
// 2.2 生成需要替换的内容
var content = '';
files.forEach(function (item) {
// 在 EcmaScript 6 的 ` 字符串中,可以使用 ${} 来引用变量
content += `
<tr>
<td><a href="">${item}></a></td>
<td align="left">2018-10-20 18:50</td>
<td align="right"> -</td>
<td>hello world!</td>
</tr>
`;
});
// 2.3 替换
data = data.toString();
// 普通的字符串解析替换,浏览器看到的结果就不一样了
data = data.replace('^_^', content);
// 3. 发送解析替换后的页面
res.end(data);
});
})
});
// 3. 绑定端口号,启动服务
server.listen(3000, function () {
console.log('running...');
});
模板页面:template.html
<html>
<head>
<title>My Item</title>
</head>
<body>
<h1>My Item</h1>
<table>
<tbody>
<tr>
<th align="left"><a href="?C=N;O=D">Name</a></th>
<th align="left"><a href="?C=M;O=A">Last modified</a></th>
<th align="left"><a href="?C=S;O=A">Size</a></th>
<th align="left"><a href="?C=D;O=A">Description</a></th>
</tr>
<tr>
<th colspan="5">
<hr>
</th>
</tr>
^_^
<tr>
<th colspan="5">
<hr>
</th>
</tr>
</tbody>
</table>
<address>node.js</address>
</body>
</html>
Apache 完善
可以点击下面的子文件
var http = require('http');
var fs = require('fs');
var path = require('path');
// 加载 art-template 模板引擎
var template = require('art-template');
// 设置 www 的根目录
var wwwDir = 'E:/desk/my-pro/QD-practice/node/2/www';
// 1. 创建 Server
var server = http.createServer();
// 2. 监听 Server 的 request 请求事件,设置请求处理函数
server.on('request', function (req, res) {
var url = req.url;
// 1.如果是文件,直接读取响应
// 2.如果是目录,读取渲染目录列表
// 3.如果目录并且有该目录中有 index.html 则直接渲染目录中的 index.html
var urlPath = path.join(wwwDir, url);
fs.stat(urlPath, function (err, stats) {
if (err) {
// return res.end(urlPath);
return res.end('404 not found');
}
if (stats.isFile()) { // 表示一个普通文件,则返回 true
fs.readdir(urlPath, function (err, data) {
if (err) {
return res.end('404 not found')
}
res.end(data);
})
} else if (stats.isDirectory()) { // 表示一个文件系统目录,则返回 true
// 返回 path 的内容
var templateStr = fs.readFileSync('./tmp/template.html').toString();
// 返回一个不包括 '.' 和 '..' 的文件名的数组。
var files = fs.readdirSync(urlPath);
// map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
// var data = files.map(function (item) {
// return {
// url:
// name:
// type:
// }
// })
// 这里只需要使用模板引擎解析替换 data 中的模板字符串就可以了
// 数据就是 files
// 之后在 template.html 文件中编写你的模板语法就行了
var htmlStr = template.render(templateStr, {
files: files
});
// 3. 发送解析替换后的页面
res.end(htmlStr);
}
});
});
// 3. 绑定端口号,启动服务
server.listen(3000, function () {
console.log('running...');
});
template.html 模板文件
<html dir="ltr" lang="zh" i18n-processed="">
<head>
<meta charset="utf-8">
<meta name="google" value="notranslate">
<style>
h1 {
border-bottom: 1px solid #c0c0c0;
margin-bottom: 10px;
padding-bottom: 10px;
white-space: nowrap;
}
table {
border-collapse: collapse;
}
th {
cursor: pointer;
}
td.detailsColumn {
-webkit-padding-start: 2em;
text-align: end;
white-space: nowrap;
}
a.icon {
-webkit-padding-start: 1.5em;
text-decoration: none;
}
a.icon:hover {
text-decoration: underline;
}
a.file {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABnRSTlMAAAAAAABupgeRAAABHUlEQVR42o2RMW7DIBiF3498iHRJD5JKHurL+CRVBp+i2T16tTynF2gO0KSb5ZrBBl4HHDBuK/WXACH4eO9/CAAAbdvijzLGNE1TVZXfZuHg6XCAQESAZXbOKaXO57eiKG6ft9PrKQIkCQqFoIiQFBGlFIB5nvM8t9aOX2Nd18oDzjnPgCDpn/BH4zh2XZdlWVmWiUK4IgCBoFMUz9eP6zRN75cLgEQhcmTQIbl72O0f9865qLAAsURAAgKBJKEtgLXWvyjLuFsThCSstb8rBCaAQhDYWgIZ7myM+TUBjDHrHlZcbMYYk34cN0YSLcgS+wL0fe9TXDMbY33fR2AYBvyQ8L0Gk8MwREBrTfKe4TpTzwhArXWi8HI84h/1DfwI5mhxJamFAAAAAElFTkSuQmCC ") left top no-repeat;
}
a.dir {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAd5JREFUeNqMU79rFUEQ/vbuodFEEkzAImBpkUabFP4ldpaJhZXYm/RiZWsv/hkWFglBUyTIgyAIIfgIRjHv3r39MePM7N3LcbxAFvZ2b2bn22/mm3XMjF+HL3YW7q28YSIw8mBKoBihhhgCsoORot9d3/ywg3YowMXwNde/PzGnk2vn6PitrT+/PGeNaecg4+qNY3D43vy16A5wDDd4Aqg/ngmrjl/GoN0U5V1QquHQG3q+TPDVhVwyBffcmQGJmSVfyZk7R3SngI4JKfwDJ2+05zIg8gbiereTZRHhJ5KCMOwDFLjhoBTn2g0ghagfKeIYJDPFyibJVBtTREwq60SpYvh5++PpwatHsxSm9QRLSQpEVSd7/TYJUb49TX7gztpjjEffnoVw66+Ytovs14Yp7HaKmUXeX9rKUoMoLNW3srqI5fWn8JejrVkK0QcrkFLOgS39yoKUQe292WJ1guUHG8K2o8K00oO1BTvXoW4yasclUTgZYJY9aFNfAThX5CZRmczAV52oAPoupHhWRIUUAOoyUIlYVaAa/VbLbyiZUiyFbjQFNwiZQSGl4IDy9sO5Wrty0QLKhdZPxmgGcDo8ejn+c/6eiK9poz15Kw7Dr/vN/z6W7q++091/AQYA5mZ8GYJ9K0AAAAAASUVORK5CYII= ") left top no-repeat;
}
a.up {
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmlJREFUeNpsU0toU0EUPfPysx/tTxuDH9SCWhUDooIbd7oRUUTMouqi2iIoCO6lceHWhegy4EJFinWjrlQUpVm0IIoFpVDEIthm0dpikpf3ZuZ6Z94nrXhhMjM3c8895977BBHB2PznK8WPtDgyWH5q77cPH8PpdXuhpQT4ifR9u5sfJb1bmw6VivahATDrxcRZ2njfoaMv+2j7mLDn93MPiNRMvGbL18L9IpF8h9/TN+EYkMffSiOXJ5+hkD+PdqcLpICWHOHc2CC+LEyA/K+cKQMnlQHJX8wqYG3MAJy88Wa4OLDvEqAEOpJd0LxHIMdHBziowSwVlF8D6QaicK01krw/JynwcKoEwZczewroTvZirlKJs5CqQ5CG8pb57FnJUA0LYCXMX5fibd+p8LWDDemcPZbzQyjvH+Ki1TlIciElA7ghwLKV4kRZstt2sANWRjYTAGzuP2hXZFpJ/GsxgGJ0ox1aoFWsDXyyxqCs26+ydmagFN/rRjymJ1898bzGzmQE0HCZpmk5A0RFIv8Pn0WYPsiu6t/Rsj6PauVTwffTSzGAGZhUG2F06hEc9ibS7OPMNp6ErYFlKavo7MkhmTqCxZ/jwzGA9Hx82H2BZSw1NTN9Gx8ycHkajU/7M+jInsDC7DiaEmo1bNl1AMr9ASFgqVu9MCTIzoGUimXVAnnaN0PdBBDCCYbEtMk6wkpQwIG0sn0PQIUF4GsTwLSIFKNqF6DVrQq+IWVrQDxAYQC/1SsYOI4pOxKZrfifiUSbDUisif7XlpGIPufXd/uvdvZm760M0no1FZcnrzUdjw7au3vu/BVgAFLXeuTxhTXVAAAAAElFTkSuQmCC ") left top no-repeat;
}
html[dir=rtl] a {
background-position-x: right;
}
#parentDirLinkBox {
margin-bottom: 10px;
padding-bottom: 10px;
}
#listingParsingErrorBox {
border: 1px solid black;
background: #fae691;
padding: 10px;
display: none;
}
</style>
<title id="title">hello</title>
</head>
<body>
<div id="listingParsingErrorBox">糟糕!Google Chrome无法解读服务器所发送的数据。请<a href="http://code.google.com/p/chromium/issues/entry">报告错误</a>,并附上<a href="LOCATION">原始列表</a>。</div>
<h1 id="header">www 目录</h1>
<div id="parentDirLinkBox" style="display:none">
<a id="parentDirLink" class="icon up">
<span id="parentDirText">[上级目录]</span>
</a>
</div>
<table>
<thead>
<tr class="header" id="theader">
<th onclick="javascript:sortTable(0);">名称</th>
<th class="detailsColumn" onclick="javascript:sortTable(1);">
大小
</th>
<th class="detailsColumn" onclick="javascript:sortTable(2);">
修改日期
</th>
</tr>
</thead>
<tbody id="tbody">
{{each files}}
<tr>
<td data-value="apple/"><a class="icon dir" href="{{$value}}">{{$value}}</a></td>
<td class="detailsColumn" data-value="0"></td>
<td class="detailsColumn" data-value="1509589967">2017/11/2 上午10:32:47</td>
</tr>
{{/each}}
</tbody>
</table>
</body>
</html>