底层 HTTP 模块
Express 框架建立在 node.js 内置的 http 模块上,框架的核心是对 HTTP 模块的再包装
http 模块生成服务器的原始代码如下:
1 2 3 4 5 6 7 8
| var http = require("http");
var app = http.createServer(function(request, response) { response.writeHead(200, {"Content-Type": "text/plain"}); response.end(" express hahahah"); });
app.listen(4040, "localhost");
|
上面的代码关键是 http 模块的 createServer 方法,表示生成一个 http 服务器实例,该方法接受一个回调函数,回调函数的两个参数分别代表 HTTP 请求和 HTTP 响应的 request 对象和 response 对象

上面的代码用 Express 改写如下
1 2 3 4 5 6 7 8
| var express = require('express'); var app = express();
app.get('/', function (req, res) { res.send('Hello world!'); });
app.listen(7000);
|

可以发现两端代码特别相似,原来是用 http.createServer 方法新建一个 app 实例,现在则是用 Express 的构造方法,生成一个 Epress 实例,两种方法的回调函数都是相同的,
Express 等于在 HTTP 模块之上,加了一个中间层
什么是中间件
中间件就是处理 HTTP 请求的函数,
特点:一个中间件处理完再传递给下一个中间件,APP 实例在运行中会调用一系列的中间件
每个中间件可以从 APP 实例接收三个参数 request (代表 HTTP 请求),response (代表 HTTP 响应),next 回调函数 (代表下一个中间件),每一个中间件都可以对 HTTP 请求 (request 对象) 进行加工,并且决定是否调用 next 方法,将 request 对象再传给下一个中间件
最简单的中间件
1 2 3 4 5 6 7 8 9 10 11 12
| function uselessMiddleware(req,res,next){ next() }
上面代码的next就是下一个中间件。如果它带有参数,则代表抛出一个错误,参数为错误文本。
function uselessMiddleware(req, res, next) { next('出错了!'); } 抛出错误以后,后面的中间件将不再执行,直到发现一个错误处理函数为止。
|
use 方法
use 是 express 注册中间件的方法,使用 app.use 方法,注册了两个中间件,收到 HTTP 请求后,先调用第一个中间件,根据 next () 确定是否把 request 对象传递到下一个中间件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| var express = require("express"); var http = require("http");
var app = express();
app.use(function(request, response, next) { console.log("In comes a " + request.method + " to " + request.url); next(); });
app.use(function(request, response) { response.writeHead(200, { "Content-Type": "text/plain" }); response.end("Hello world!\n"); });
http.createServer(app).listen(1337);
|
use 方法内部通过 request.url
的属性可以根据访问路径进行判断,据此就能实现简单的路由,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| var express = require("express"); var http = require("http"); var app = express();
app.use(function(request,response,next){ if(request.url == "/"){ response.writeHead(200, { "Content-Type": "text/plain" }); response.end("Welcome to the homepage!\n"); }else{ next(); } })
app.use(function(request, response, next) { if (request.url == "/about") { response.writeHead(200, { "Content-Type": "text/plain" }); } else { next(); } }); app.use(function(request, response) { response.writeHead(404, { "Content-Type": "text/plain" }); response.end("404 error!\n"); });
http.createServer(app).listen(1337);
|
另外一种比较清晰的方式(上面代码表示,只对根目录的请求,调用某个中间件。
)
app.use('/path', someMiddleware);
按照这个思想,改造中间件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| var express = require("express"); var http = require("http");
var app = express();
app.use("/home", function(request, response, next) { response.writeHead(200, { "Content-Type": "text/plain" }); response.end("Welcome to the homepage!\n"); });
app.use("/about", function(request, response, next) { response.writeHead(200, { "Content-Type": "text/plain" }); response.end("Welcome to the about page!\n"); });
app.use(function(request, response) { response.writeHead(404, { "Content-Type": "text/plain" }); response.end("404 error!\n"); });
http.createServer(app).listen(1337);
|