zoukankan      html  css  js  c++  java
  • 使用node.js仿写Apache

    Git仓库:https://github.com/mandongpiaoxue/apache

    本文原创,引用请注明出处

    文件说明:

    config.json          //配置文件
    images.js            //引入的svg图片
    server.js             //服务器文件
    run.bat              //window中启动文件,双击立即启动服务

    1. config.json文件的配置

    {
        "index": "index",    //首页名字
        "deny": {              //拒绝IP的访问
            "ips": [
                "192.168.0.10"
            ]
        },
        "hosts": [
            {
                "host": "127.0.0.1",     //配置域名
                "dir": "D:/www"          //配置路径
            },
            {
                "host": "www.man.cn",
                "dir": "D:/www"
            }
        ]
    }        

     2. run.bat文件代码

    @cd /d %~dp0
    @echo Node.js服務器啟動成功
    @node server.js

    3.  server.js文件代码与说明

    3.1 引入模块和文件

    //引入模块
    const http = require('http') const url = require('url') const fs = require('fs') const path = require('path') const images = require('./images') //引入图片
    //定义变量
    var config = [] var ips = [] var index = ''
    //读取配置文件 fs.readFile(path.join(__dirname,
    'config.json'), (err, data) => { config = JSON.parse(data.toString()) ips = config.deny.ips index = config.index })

    3.2 写readfile函数:方便我们使用promise,简洁写代码

    function readFile(file) {
        return new Promise((resolve, reject) => {
            fs.readFile(file, (error, data) => {
                if (error) {
                    reject(error)
                } else {
                    resolve(data)
                }
            })
        })
    }

    3.3 server代码及注释

    http
        .createServer(function (req, res) {
            /* 獲取遠程IP */
            let remoteIp = req.socket.remoteAddress.substr(7)
            /* 屏蔽指定IP */
            ips.forEach(ip => {
                if (ip === remoteIp) res.end('404 file no found!')
            })
            /* 获取host,即域名 */
            let host = req.headers.host
            /* 如果通過非80端口接入,會存在protocol,否則為null */
            let protocol = url.parse(host).protocol
            if (protocol) host = protocol.slice(0, -1)
            /* 格式化Url */
            let urlObject = url.parse(req.url, true)
            /* 获取路径名 */
            let pathname = urlObject.pathname
            pathname = decodeURIComponent(pathname)
            /* 获取后缀名 */
            let ext = path.parse(pathname).ext
            /* 查找访问的域名对应的相关配置 */
            let server = config.hosts.find((v, i) => {
                return v.host === host
            })
            /* 讀取匹配的路徑 */
            if (!server.dir) res.end('域名未指向路径!')
            fs.readdir(server.dir, (error, data) => {
                if (error) res.end('域名指向路径错误')
            })
            switch (ext) {
                /* 對.htm和.htm文件進行頭設置,防止部分html或htm文件無法解讀 */
                case '.html':
                    res.setHeader('Content-Type', 'text/html;chartset=utf-8')
                    break
                case '.htm':
                    res.setHeader('Content-Type', 'text/html;chartset=utf-8')
                    break
                case '.txt':
                    res.setHeader('Content-Type', 'text/plain;chartset=utf-8')
                    break
                case '.css':
                    res.setHeader('Content-Type', 'text/css;chartset=utf-8')
                    break
                case '.doc':
                    res.setHeader('Content-Type', 'application/msword;chartset=utf-8')
                    break
            }
            let dir = server.dir
            let filePath = dir + pathname
            /* 以文件夾/目录形式讀取Url */
            fs.readdir(filePath, (ed, dd) => {
                if (ed) {
                    /* 直接讀取文件 */
                    readFile(filePath + '')
                        .then(d1 => {
                            res.end(d1)
                        }, e1 => {
                            res.setHeader('Content-Type', 'text/html;chartset=utf-8')
                            /* 以省略.htm的形式讀取文件 */
                            return readFile(filePath + '.htm')
                        })
                        .then(d2 => {
                            res.end(d2)
                        }, e2 => {
                            /* 以省略.html的形式讀取文件 */
                            return readFile(filePath + '.html')
                        })
                        .then(d3 => {
                            res.end(d3)
                        }, e3 => {
                            res.end('404 file no found!')
                        })
                } else {
                    /* 以html类型读取文件,所以设置响应头为'text/html;chartset=utf-8' */
                    res.setHeader('Content-Type', 'text/html;chartset=utf-8')
                    /* 讀取目錄下的index.html文件 */
                    readFile(filePath + '/' + index + '.html')
                        .then(d1 => {
                            res.end(d1)
                        }, e1 => {
                            /* 讀取目錄下的index.htm文件 */
                            return readFile(filePath + '/' + index + '.htm')
                        })
                        .then(d2 => {
                            res.end(d2)
                        }, e2 => {
                            /* 讀取目錄下的index文件 */
                            return readFile(filePath + '/' + index)
                        })
                        .then(d3 => {
                            res.end(d3)
                        }, e3 => {
                            /* 如果没有index文件,则讀取目錄下的文件 */
                            let pna = pathname.split('/')
                            pna.pop()
                            let name = pna.pop()
                            let pn = pathname.slice(0, -1)
                            let pnl = pn.lastIndexOf('/')
                            let upPath = pathname.slice(0, pnl + 1)
                            let ds = `
                                <meta charset="UTF-8">
                                <title>${name}</title>
                                <style>
                                    body{padding:20px 50px;}
                                </style>
                                <a style="display:block;height:32px;" href="${upPath}">${images.back}</a>
                            `
                            dd.forEach(file => {
                                if (file.search('\.') > -1) {
                                    ds += `<a style="display:block;height:32px;" href="${pathname + file}"><span style="height:32px;line-height:32px;float:left;display:block;">${images.file}</span><span style="height:32px;line-height:32px;float:left;display:block;">${file}</span></a>`
                                } else {
                                    ds += `<a style="display:block;height:32px;" href="${pathname + file + '/'}"><span style="height:32px;line-height:32px;float:left;display:block;">${images.folder}</span><span style="height:32px;line-height:32px;float:left;display:block;">${file}</span></a>`
                                }
                            })
                            res.end(ds)
                        })
                }
            })
        })
        .listen(80, function (err) {
            if (err) console.log(err)
        })

     4. 效果图

  • 相关阅读:
    聊聊click延迟和点击穿透
    setAttribute的浏览器兼容性(转)
    浅谈JS中的高级函数
    跨域总结
    本地存储小结
    ubuntu下pip的安装和使用
    并发编程艺术-锁类型以及底层原理
    HTTP协议以及HTTP2.0/1.1/1.0区别
    Paxos
    jvm垃圾收集器总结jdk1.7
  • 原文地址:https://www.cnblogs.com/mandongpiaoxue/p/11619020.html
Copyright © 2011-2022 走看看