基于node.js的静态资源服务器 ----阿里面试题

最近远程面试阿里给的一个面试题 手撸一个基于node的静态资源服务器。以下是我个人的思路

直接先贴代码

const http = require('http')
const fs = require('fs')
const path = require('path')
const server = http.createServer()

server.on('request', (req, res) => {
  res.setHeader('Access-Control-Allow-Origin', '*') // 设置跨域
  controllers(req, res)
  // readStatic(url, res)
})
// 4.启动服务器
server.listen(8080, () => {
  console.log('start is server')
})

let redis = {}

setInterval(() => { // 用定时器有点草率但是没时间了 先这样凑合做个简单的清楚
  redis = {} // 时间够的话 指定不会这样清,会对每个key进行一个时间绑定。如果时间到期则回清除 类似于session
}, 3000)

const controllers = async (req, res) => {
  const url = req.url
  if (url === '/favicon.ico') return
  if (url === '/') {
    const files = await getFilesName()
    res.writeHead(200, { 'Content-Type': 'text/html;charset=utf-8' })
    let str = ''
    for (var i = 0; i < files.length; i++) {
      str = str + `<a href=${files[i]}>${files[i]}</a><br>`
    }
    const query = 'https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js'
    res.end(`<body><div id='router'></div></body><script src="${query}"></script><script> document.getElementById('router').innerHTML ='${str}'</script> `)
    res.end(`<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
    <script>
        let domA = document.getElementsByTagName("a")
        for(var i=0;i<domA.length;i++){
          let url = http://localhost:8080/+ domA[i].innerHTML
          domA[i].onclick = function(){
            $.ajax({url:url,type:'GET',success:function(data){
              console.log(data)
            }})
          }
        }
    </script>`)
  } else {
    readStatic(url, res)
  }
}

const readStatic = function (url, res) {
  fs.readFile(path.join(__dirname, 'static', url), (_err, data) => { // 路径拼接去static目录下找对应的文件
    const urlItem = url.split('.')
    const Contenttype = mime[urlItem[1]] || 'application/octet-stream'

    if (urlItem[1] === undefined) {
      if (!redis[url]) {
        res.writeHead(200, {
          'Content-Type': 'application/octet-stream',
          'Content-Disposition': `attachment; filename=${urlItem[0]}`
        })
        fs.createReadStream(`${__dirname}/static${url}`).pipe(res)
        redis[url] = true
      } else {
        res.writeHead(403, { 'Content-type': Contenttype })
        res.end()
      }
    } else {
      res.writeHead(200, { 'Content-Type': Contenttype + ';charset=utf-8' })
      res.end(data)
    }
  })
}

const getFilesName = () => {
  return new Promise((resolve, reject) => {
    fs.readdir(`${__dirname}/static`, function (_err, data) {
      if (_err) {
        return reject(_err)
      }
      const item = []
      for (const value of data) {
        item.push(value)
      }
      resolve(item)
    })
  })
}

// const isBuffer = function (str) {
//   return str && typeof str === 'object' && Buffer.isBuffer(str)
// }

const mime = {
  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'
}

  • 首先需要建立一个app.js文件,该文件主要用于搭建服务器,所谓的静态资源服务器就是把服务器上的文件通过http进行发送或者说是做处理
  • 比如通过请求某个地址需要把某个文件夹下面的html渲染在浏览器上,或者说下载某个文件,也或者说把某个文件夹下面的txt文件的内容显示在浏览器上。html的渲染不是显示源码而是显示的是网页
  • 主文件app.js建立好后就需要 建一个静态文件夹用于放我们需要显示或者下载的文件

在这里插入图片描述

  • 我的目录,我在static下面放了四个类型不一样的文件,我的目的是通过请求/index.js路径就显示源码在网页,请求/index.html就把html渲染在网页,/index就是直接下载该文件

  • 首先需要搭个基本的服务器 这个时候就会用到http模块 ,服务器搭建完成后

  • 我的做法是通过后缀名去区分不同的文件,通过区分不同的文件给他设置对应的content-type类型
    -在这里插入图片描述

  • 一些类型都封装在mine对象中

  • 在这里插入图片描述

  • 还有一个需求则是把根目录下的文件当做a标签一样点击后进行不同的操作,其实就是点击后发送ajax请求,当用户请求127.0.0.1:8080/路径的时候我会返他一个我自己的html页面这个页面是会显示static目录下的文件如图
    在这里插入图片描述

  • 其实就是MVC的模板渲染我这个是最基础的,如果你把Html当做字符串返回在浏览器上和本地加载html是一样的但是 content-type得设成 text/html 否则浏览器是不会知道你给他了一个什么东西,这里偷了个懒 引入了百度的jquery写了个ajax请求。没有直接写原生的XMLHttpRequest

在这里插入图片描述

总结:其实就是构建一个Http服务然后在本地建立一个static的静态资源库,然后通过fs文件操作来进行数据返回,根据不同的需求返回不同的结果。难点在于对http的content-type的理解,写的时候因为不熟悉踩了不少坑。这个代码还可以继续的优化。考察的就是代码能力,可惜,平时库用太多忘了http.js的操作和content-type的设置,其实如果扩展起来就类似于nginx的功能。 还是太菜没抓住机会!

码云地址:https://gitee.com/gong-yongchao/static-server
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值