node——8-node.js 实现 apache 功能

初步实现 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}&gt;</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>

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值