手写一个服务器(一)

65 篇文章 0 订阅
45 篇文章 1 订阅

学习了很多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 封装成为一个方法

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值