express框架, 为什么会混合使用内置的 http(s) 模块?
发布于 作者:苏南大叔 来源:程序如此灵动~
在nodejs
的网站后端领域里面,express
框架可能是入门必备的框架。单独的express
就是可以运行的,但是,为啥有的例子里面,会出现和nodejs
内置的http
/https
合用的场景呢?要知道,某种意义上来说,express
和http
模块解决的是同样的事情。
苏南大叔的“程序如此灵动”博客,记录苏南大叔的代码编程经验总结。测试环境:win10
,nodejs@20.18.0
,express@4.21.2
。本文试图解决一个疑惑,有关express
和http
合用的合理性问题。
express单独用例
参考代码如下:
var express = require("express");
var app = express();
app.use(express.static('public'));
app.use((request, response, next) => {
console.log(request.method + " " + request.url);
next();
});
app.get("*", (request, response, next) => {
response.end(request.url);
});
app.listen(80, function () { console.log('http://localhost:%s', this.address().port) });
本文并不是解释express
的具体使用情况的,所以,更多使用方法可以参考下面的文章:
http模块单独用例
var http = require("http");
var app = http.createServer(function (request, response) {
console.log(request.method + " " + request.url);
response.writeHead(200, { "Content-Type": "text/plain" });
response.end(request.url);
});
app.listen(80, () => console.log('http://localhost:%s', app.address().port));
express和http模块合用例子
既生瑜何生亮?为啥两者要合用?那是因为:express
框架本来就是基于http
模块的,两者本身也没有太明显的竞争关系。
let express = require("express");
let _express = express();
_express.use(express.static('public'));
_express.use((request, response, next) => {
console.log(request.method + " " + request.url);
next();
});
_express.get("*", (request, response, next) => {
response.end(request.url);
});
// _express.listen(80, function(){console.log('http://localhost:%s', this.address().port)});
let http = require("http");
let httpServer = http.createServer(_express);
httpServer.listen(80, () => console.log('http://localhost:%s', httpServer.address().port));
还可以开两个端口,
// ...
_express.listen(80, function(){console.log('http://localhost:%s', this.address().port)});
// ...
httpServer.listen(81, () => console.log('http://localhost:%s', httpServer.address().port));
本来express
就可以.listen()
,为啥非要使用http.createServer().listen()
包装一下呢?
express源码
点开express.listen()
到express
的源码。就可以看到express
官方推荐使用http
或者https
模块的注释。不过是个interface
,通过关键字找到实现代码的话,就可以看到express.listen()
的实现代码:
/**
* Listen for connections.
*
* A node `http.Server` is returned, with this
* application (which is a `Function`) as its
* callback. If you wish to create both an HTTP
* and HTTPS server you may do so with the "http"
* and "https" modules as shown here:
*
* var http = require('http')
* , https = require('https')
* , express = require('express')
* , app = express();
*
* http.createServer(app).listen(80);
* https.createServer({ ... }, app).listen(443);
*
* @return {http.Server}
* @public
*/
app.listen = function listen() {
var server = http.createServer(this);
return server.listen.apply(server, arguments);
};
所以,你所疑惑的代码,其实只是一个变换的写法罢了。express
的listen()
方法,本来也调用的是http
模块。那么,这样来说,两者的合用代码,就显得不那么奇怪了。
express 合用 http 和 https
新的监听三个端口的完整代码:
let express = require("express");
let _express = express();
_express.use(express.static('public'));
_express.use((request, response, next) => {
console.log(request.method + " " + request.url);
next();
});
_express.get("*", (request, response, next) => {
response.end(request.url);
});
_express.listen(80, function () { console.log('http://localhost:%s', this.address().port) });
let http = require("http");
let httpServer = http.createServer(_express);
httpServer.listen(81, () => console.log('http://localhost:%s', httpServer.address().port));
let https = require('https');
let fs = require('fs');
let httpsServer = https.createServer({
key: fs.readFileSync('./cert/cert-key.pem'),
cert: fs.readFileSync('./cert/cert.pem')
}, _express);
httpsServer.listen(82, () => console.log('https://localhost:%s', httpsServer.address().port));
结语
所以,结论是:express
和http
模块的关系,并不是对立,而是amigo
的关系。


