前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >35·灵魂前端工程师养成-使用nodejs实现简单nginx功能

35·灵魂前端工程师养成-使用nodejs实现简单nginx功能

作者头像
DriverZeng
发布2022-10-31 18:11:14
5590
发布2022-10-31 18:11:14
举报

-曾老湿, 江湖人称曾老大。


-多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作。 -擅长Web集群架构与自动化运维,曾负责国内某大型金融公司运维工作。 -devops项目经理兼DBA。 -开发过一套自动化运维平台(功能如下): 1)整合了各个公有云API,自主创建云主机。 2)ELK自动化收集日志功能。 3)Saltstack自动化运维统一配置管理工具。 4)Git、Jenkins自动化代码上线及自动化测试平台。 5)堡垒机,连接Linux、Windows平台及日志审计。 6)SQL执行及审批流程。 7)慢查询日志分析web界面。


实现nginx静态服务器


改进之前的server.js

代码语言:javascript
复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)

  if(path === '/'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    response.write(`
        <!DOCTYPE html>
        <head>
            <link rel="stylesheet" href="/x">
        </head>
        <body>
            <h1>曾老湿</h1>
            <script src="/y"></script>
        </body>
    `)
    response.end()
  } else if(path === '/x'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/css;charset=utf-8')
    response.write(`body{color: red;}`)
    response.end()
  } else if(path === '/y'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/javascript;charset=utf-8')
    response.write(`console.log('这是JS内容')`)
    response.end()
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)

优化第一步:用户输入啥访问啥页面

先把项目运行起来。

代码语言:javascript
复制
MacBook-pro:static_server driverzeng$ node-dev server.js 8888

我们先写一个主页面

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>主页面</title>
</head>
<body>
    这个是主页:index.html
</body>
</html>

然后server.js加载页面

代码语言:javascript
复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)

  if(path === '/'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    response.write(fs.readFileSync('public/index.html'))
    response.end()
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)

那我再加一个css

我还得写一个判断

style.css

代码语言:javascript
复制
body{
    color:red;
}

server.js

代码语言:javascript
复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)

  if(path === '/'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    response.write(fs.readFileSync('public/index.html'))
    response.end()
  } else if(path === '/style.css'){
    response.statusCode = 200
    response.setHeader('Content-Type', 'text/css;charset=utf-8')
    response.write(fs.readFileSync('public/style.css'))
    response.end()
  } else {
    response.statusCode = 404
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    response.write(`你输入的路径不存在对应的内容`)
    response.end()
  }

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)

上面的代码好鸡肋。

一个判断一个路径,要是有100个页面,我得写100个判断?

接下来我们就创建100个文件...emmm... 太多了,3个吧。

 里面的内容,就是文件名,接下来我们尝试,用户输入啥,就读取啥文件

代码语言:javascript
复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)


    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    const filePath =  path
    response.write(fs.readFileSync(`public${filePath}`))
    response.end()

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)

实现了,写啥就读取啥。

但是....注意啦,如果写一个不存在的路径会怎么样?

额...我擦嘞,服务直接挂了。

解决bug


不存在的页面不让服务挂

我们使用try ,catch一下,抓一下错误。

代码语言:javascript
复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)


    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    const filePath = path
    let content
    try {
        content =  fs.readFileSync(`public${filePath}`)
    } catch (error) {
        content = '文件:' +filePath+'不存在啊,大兄弟,你这是要上天啊?'
        response.statusCode = 404
    }
    response.write(content)
    response.end()

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)

不存在就报错,存在就正常显示页面。


访问/即访问默认主页

但是....emm... mmp... 如果访问/也是不存在

如何是好?继续解决bug

代码语言:javascript
复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)


    response.statusCode = 200
    response.setHeader('Content-Type', 'text/html;charset=utf-8')
    var accept = request.headers["accept"];
    console.log("accept:");
    console.log(accept);
    const filePath = path === '/' ? '/index.html' : path    // 默认首页
    let content
    try {
        content =  fs.readFileSync(`public${filePath}`)
    } catch (error) {
        content = '文件:' +filePath+'不存在啊,大兄弟,你这是要上天啊?'
        response.statusCode = 404
    }
    response.write(content)
    response.end()

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)

呦西,但是 还有一个问题,就是代码中 Content-Type 永远都是text/html

这样不就智障了吗?我要解析解析一个css文件,你按照html来解析?


根据访问文件内容选择解析

获取请求路径的后缀。

代码语言:javascript
复制
console.log(filePath.lastIndexOf('.'))

可以看到当访问a.html的时候,第2个是'.' 当访问style.css的时候,第6个是'.'

我们就可以根据这个'.'来判断文件的后缀,然后使用对应的解析

代码语言:javascript
复制
const index = filePath.lastIndexOf('.')
const backend = filePath.substring(index)
console.log(backend)

打印一下,后缀是啥,获取到没有。

使用hash表数据结构,来把后缀替换到Content-Type中

代码语言:javascript
复制
var http = require('http')
var fs = require('fs')
var url = require('url')
var port = process.argv[2]

if(!port){
  console.log('请指定端口号好不啦?\nnode server.js 8888 这样不会吗?')
  process.exit(1)
}

var server = http.createServer(function(request, response){
  var parsedUrl = url.parse(request.url, true)
  var pathWithQuery = request.url 
  var queryString = ''
  if(pathWithQuery.indexOf('?') >= 0){ queryString = pathWithQuery.substring(pathWithQuery.indexOf('?')) }
  var path = parsedUrl.pathname
  var query = parsedUrl.query
  var method = request.method

  /******** 从这里开始看,上面不要看 ************/

  console.log('有个傻子发请求过来啦!路径(带查询参数)为:' + pathWithQuery)

    response.statusCode = 200
    const filePath = path === '/' ? '/index.html' : path    // 默认首页
    const index = filePath.lastIndexOf('.')
    const backend = filePath.substring(index)
    const fileTypes = {
        '.html':'text/html',
        '.css':'text/css',
        '.js':'text/javascript',
        '.json':'application/json',
        '.png':'image/png',
        '.jpg':'image/jpeg',
        '.jpeg':'image/jpeg',
        '.gif':'image/gif'
    }
    response.setHeader('Content-Type', `${fileTypes[backend] || 'text/html'};charset=utf-8`)
    console.log(backend)
    let content
    try {
        content =  fs.readFileSync(`public${filePath}`)
    } catch (error) {
        content = '文件:' +filePath+'不存在啊,大兄弟,你这是要上天啊?'
        response.statusCode = 404
    }
    response.write(content)
    response.end()

  /******** 代码结束,下面不要看 ************/
})

server.listen(port)
console.log('监听 ' + port + ' 成功\n请用在空中转体720度然后用电饭煲打开 http://localhost:' + port)

尝试放入图片


引用文件

代码语言:javascript
复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>主页面</title>
    <link rel="stylesheet" href="./style.css">
</head>
<body>
    <div>
        <img src="./naruto.jpeg" alt="">
        <script src="./c.js"></script>
    </div>
    这个是主页:index.html
</body>
</html>

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-05-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 实现nginx静态服务器
  • 优化第一步:用户输入啥访问啥页面
  • 解决bug
相关产品与服务
堡垒机
腾讯云堡垒机(Bastion Host,BH)可为您的 IT 资产提供代理访问以及智能操作审计服务,为客户构建一套完善的事前预防、事中监控、事后审计安全管理体系,助力企业顺利通过等保测评。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档