学习了很多HTTP的知识,这里通过手写一个HTTP服务来运用之前用到的知识。
搭建项目结构
//目录结构
// 新建文件夹static
./static
+-- public
| +-- index.html
| +-- index.css
| +-- index.js
+-- src
| +-- app.js
| +-- config.js
+-- package.json
//public 这里的目录主要是在写服务的时候用到
// package.json 使用npm init -y [yarn init -y] 生成
./src/confing.js
内容
// 这里是项目的启动配置
// hostname: 默认host
// port:默认端口
// dir: 默认服务器启动项目目录
// debug: 是一个第三方模块,主要配合调试使用,详情请去 https://www.npmjs.com/package/debug
let path = require('path')
// 启动服务的配置项
let config = {
hostname: 'localhost',
port: 3000,
dir: path.join(__dirname, '..', 'public')
}
let debug = require('debug')('static:config')
debug('config')
module.exports = config
./src/app.js
内容
// 引入需要的模块
let config = require('./config')
let path = require('path')
let fs = require('fs')
let mime = require('mime')
let chalk = require('chalk')
let util = require('util')
let url = require('url')
let http = require('http')
let supervisor = require('supervisor')
let stat = util.promisify(fs.stat)
// debug后面放置的是参数,可以根据后边的参数决定是否打印
// debug 设置环境变量: set DEBUG=XXX
// powershell设置环境变量: $env:DEBUG = "*,-not_this"
let debug = require('debug')('static:app')
// var debug = require('debug');
// console.log(chalk.green('hello'))
// debug('app')
// supervisor 热更新模块
// npm install supervisor
// 使用: supervisor app.js
// 创建服务
class Server {
constructor () {
// 配置参数
this.config = config
}
// 服务启动
start () {
// 拿到hots, port
let {hostname, port} = this.config
// 新建服务将
let server = http.createServer(this.handleRequest())
// 监听指定host,port
let url = `http://${hostname}:${chalk.green(port)}`
debug(url) // 打印日志
server.listen(port, hostname)
}
// 服务器处理函数
handleRequest () {
// 在函数执行的时候需要返回一个函数,不然无法监听事件
// 这里使用箭头函数可以避免this问题
return async(req, res) => {
// 解析路径
let {pathname} = url.parse(req.url)
// 拼接完整路径
let p = path.join(this.config.dir, '.' + pathname)
// 检测文件是否存在
try {
let statObj = await stat(p)
// 判断 如果当前路径是目录,则展示内容列表,如果是文件直接展示文件内容
if (statObj.isDirectory()) {
// 文件目录
} else {
// 文件 直接返回
// 压缩
// 缓存
// 断点续传
console.log('request')
res.setHeader('Content-Type', mime.getType(p) + ';charset=utf8')
fs.createReadStream(p).pipe(res)
}
} catch (error) {
res.statusCode = 404
res.end()
}
}
}
}
// 创建服务势力4, 并启动
let server = new Server()
server.start()
./public
目录的内容
这里的内容只是用来测试服务用,所以的都是最简单的代码
// index.css
h1{
font-size: 60px;
text-align: center;
padding-top: 100px;
}
// index.js
console.log('index.js')
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>server demo</title>
<link rel="stylesheet" href="/index.css">
</head>
<body>
<h1>This is server demo!</h1>
<script src="/index.js"></script>
</body>
</html>
总结
到目前位置,我们已经完成了一个静态服务器,并可以在
cmd: node ./src/app
启动服务,并查看访问服务下一节我们将sendFile, sendError 封装成为一个方法