NodeJS 搭建简单的HTTP服务

前言

最早接触nodejs是在写前端时,发现下载各种框架比较麻烦,而nodejs的npm包管理挺方便,于是就开始用起来,但是经过对nodejs的学习,发现它不仅能用来写前端,后端的开发也是支持的,这里记录一下学习nodejs的http模块,如何建立一个简单的HTTP服务。使用的是V14.8.0版本的NodeJS,对ES6(ES 2015)语法特性的支持已经比较多了。

最简单的HTTP服务

创建index.js文件,代码如下

const http = require('http');

const app = http.createServer((request, response) => {
    console.log('client access to', request.url);
    console.log(request.headers);
    response.writeHead(200);
    response.end('Hello NodeJS');
});
app.listen(3000);
console.log('Server listen on 3000...');

保存文件,打开命令行,进入到文件所在的目录下,运行如下命令
node index.js
可以看到有如下的输出,说明启动成功了

$ node index.js 
Server listen on 3000...

然后使用Postmen或者其它工具请求http://localhost:3000,我使用的是VS Code的rest client工具请求,响应结果如下

接下来再写个功能稍微多一点的

地址路由

创建一个router.js文件,创建两个类,分别是HanderRouter类,用来管理和配置请求以及响应。

class Handler {
    constructor() {
        this.path = "/";
        // 默认的响应Code为404
        this.code = 404;
        // 默认的响应内容类型为json
        this.headers = {
            "Content-type": "application/json",
        };
        // 默认情况下,找不到路径时默认返回一个404的响应
        this.data = JSON.stringify({
            code: 404,
            msg: "Not Found",
            values: [],
        });
    }

    /**
     * 注册响应参数
     * @param {String} path 请求地址
     * @param {Number} code 状态码
     * @param {JSON} headers 响应头
     */
    reg(path, code, headers) {
        this.path = path;
        if (code) {
            this.code = code;
        }
        if (headers) {
            this.headers = headers;
        }
        return this;
    }

    /**
     * 设置期望的响应数据
     * @param {any} data 直接设置响应数据
     * @param {Function} callback 通过回调函数的返回值设置响应数据
     */
    end(data, callback) {
        if (callback) {
            data = callback();
        }
        if (data) {
            if (this.headers["Content-type"] || this.headers["content-type"]) {
                let value = this.headers["Content-type"] || this.headers["content-type"];
                if (value.includes("application/json")) {
                    this.data = JSON.stringify(data);
                } else {
                    this.data = data;
                }
                this.code = 200;
            }
        }
        return this;
    }

    /**
     * 接受一个函数, 函数参数分别为(响应状态码, 响应头, 响应数据)
     * @param {Function} callback 回调函数
     */
    handle(callback) {
        callback(this.code, this.headers, this.data);
    }
}
class Router {
    constructor() {
        this.handlers = {};
    }

    /**
     * 注册一个响应处理器
     * @param {Handler} handler 响应处理器
     */
    set(handler) {
        if (handler instanceof Handler) {
            this.handlers[handler.path] = handler;
        } else {
            console.error("Parameter must be of type Handler");
        }
    }

    /**
     * 根据请求地址删除一个响应处理器
     * @param {String} path 请求的url地址
     */
    remove(path) {
        try {
            delete this.handlers[path];
        } catch (error) {
            console.error(error);
        }
    }

    /**
     * 根据请求地址获取一个响应处理器,
     * 若地址不存在则返回默认的响应处理器
     * @param {String} path 请求的url地址
     */
    get(path) {
        for (const key in this.handlers) {
            if (path.startsWith(key)) {
                return this.handlers[key];
            }
        }
        return new Handler();
    }
}
module.exports = {
    Handler,
    Router,
};

配置响应和路由

创建一个listener.js文件,将上面写好的路由引入,并且配置一些请求路径

const { Handler, Router } = require("./router");

const router = new Router();
router.set(
    new Handler().reg("/list").end(null, () => {
        const c = 1024;
        return {
            code: c,
            msg: "请求成功",
            values: [
                {
                    sites: [
                        { name: "菜鸟教程", url: "www.runoob.com" },
                        { name: "google", url: "www.google.com" },
                        { name: "微博", url: "www.weibo.com" },
                    ],
                },
                {
                    sites: [
                        { name: "百度", url: "www.baidu.com" },
                        { name: "CSDN", url: "blog.csdn.net" },
                        { name: "机核", url: "www.gcores.com" },
                    ],
                },
            ],
        };
    })
);
router.set(
    new Handler().reg("/object").end({
        code: 1000,
        msg: null,
        value: {
            name: "网站",
            num: 3,
            sites: [
                { name: "Google", info: ["Android", "Google 搜索", "Google 翻译"] },
                { name: "Runoob", info: ["菜鸟教程", "菜鸟工具", "菜鸟微信"] },
                { name: "Taobao", info: ["淘宝", "网购"] },
            ],
        },
    })
);
router.set(
    new Handler().reg("/empty").end({
        code: 1000,
        msg: "This is empty",
        values: [],
    })
);
router.set(
    new Handler()
        .reg("/encoding", 201, {
            "content-type": "text/plain; charset=UTF-8",
        })
        .end("哈嘿")
);
module.exports = router;

创建服务监听

创建index.js文件,将上面的请求以及响应配置引入,注意listener.jsrouter.js这两个文件也是跟index.js在同级目录下的,文件所在位置和nodejs导入模块的路径有关,js文件可以不写后缀名。

const http = require("http");
const listener = require("./listener"); // 引入配置

const app = http.createServer((request, response) => {
    // 请求地址
    console.log("client access to", request.url);
    // 请求头
    console.log(request.headers);
    let data = "";
    // 读取请求数据,这个是异步函数
    // 监听请求的data方法可以分片读取请求发送过来的数据
    request.on("data", (chunk) => {
        data += chunk;
    });
    // 读取完成后的回调方法
    // 监听请求的end方法,在读取数据完成后输出
    request.on("end", () => {
        console.log(data.toString());
    });
    // 通过请求地址来获得响应数据,如果请求链接是没有配置的url,则返回默认的404
    const handler = listener.get(request.url);
    handler.handle((code, headers, data) => {
        // 写入响应状态码和响应头
        response.writeHead(code, headers);
        // 写入响应体
        response.end(data);
    });
});
// 监听本机localhost的3000端口,使用http://localhost:3000访问
app.listen(3000);
// 也可以开放局域网访问,但需要开启操作系统的防火墙,这样其它主机才能访问到
// 局域网访问需要用电脑的IP地址,如http://192.168.1.1:3000
// app.listen(3000, "0.0.0.0");
console.log("Server listen on 3000...");

最后,运行index.js文件,这里推荐一个nodejs工具nodemon,可以用npm或yarn直接安装,安装过程不做介绍,最后运行成功后,输出如下

$ nodemon index.js
[nodemon] 2.0.4
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node index.js`
Server listen on 3000...

使用rest client请求,结果如下

这样一个简单的HTTP服务就搭建完成了,写的非常粗糙,如果是在实际做项目中使用nodejs搭建后台的话,可以去了解下入门级别的express,如果使用typescript来开发,可以看看nest.js。

如果能看到最后,或对你有帮助的话,欢迎在评论区留言一起交流。

posted @ 2020-09-22 14:30  DerWald  阅读(787)  评论(0)    收藏  举报