《深入浅出 node.js 笔记》 - part3( 三 )


如果客户端同时接受 JSON 和 XML 格式的响应,那么它的字段值是如下这样的:
: /json,/xml
靠谱的服务器应该要顾及这个字段,然后根据自己能响应的格式做出响应,在响应报文中,通过 -Type 字段告知客户端是什么格式,如下
-Type: /json
所以的设计就是:通过 URL 设计资源,请求方法定义资源的操作,通过决定资源的表现形式
中间件
中间件的行为类似 Java 中过滤器的工作原理,就是在进入具体的业务处理之前,先让过滤器处理,比如对于每个请求我们一般都要解析 , 什么的,那么就设计对应的中间件处理完成后存储在上下文中(req 和 res,Koa2 合并为一个 )
【《深入浅出 node.js 笔记》 - part3】// 模拟中间件的实现const http = require('http')const slice = Array.prototype.sliceclass LikeExpress {constructor() {// 存放中间件的列表this.routes = {all: [], // 存放 app.use 注册的中间件get: [], // 存放 app.get 注册的中间件post: []}}// 内部实现注册的方法register(path) {const info = {}if (typeof path === 'string') { // 字符串 - 路由info.path = path// 从第二个参数开始,转换为数组,存入stackinfo.stack = slice.call(arguments, 1) // 取出剩余的参数} else { // 没有显式地传入路由则默认是根路由info.path = '/' // 省略第一个参数 -> 根目录// 从第一个参数开始,转换为数组,存入stackinfo.stack = slice.call(arguments, 0)}// { path: '', stack: [middleware, ...] }return info}use() {const info = this.register.apply(this, arguments) // 把当前函数的所有参数传入this.routes.all.push(info)}get() {const info = this.register.apply(this, arguments) // 把当前函数的所有参数传入this.routes.get.push(info)}post() {const info = this.register.apply(this, arguments) // 把当前函数的所有参数传入this.routes.post.push(info)}match(method, url) {let stack = [] // resultListif (url === '/favicon.ico') { // 小图标无视return stack}// 获取 routeslet curRoutes = []curRoutes = curRoutes.concat(this.routes.all)curRoutes = curRoutes.concat(this.routes[method])curRoutes.forEach(routeInfo => {if (url.indexOf(routeInfo.path === 0)) {// url === '/api/get-cookie' 且 routeInfo.path === '/'// url === '/api/get-cookie' 且 routeInfo.path === '/api'// url === '/api/get-cookie' 且 routeInfo.path === '/api/get-cookie'stack = stack.concat(routeInfo.stack)}})return stack}// 核心的 next 机制handle(req, res, stack) {const next = () => {// 拿到第一个匹配的中间件const middleware = stack.shift()if (middleware) {// 执行中间件函数middleware(req, res, next)}}next()}callback() {return (req, res) => {// 自己定义 res.json 方法res.json = data => {res.setHeader('Content-Type', 'application/json')res.end(JSON.stringify(data))}// 获取 url 和 method :通过这两个来获得需要经过的中间件const url = req.urlconst method = req.method.toLowerCase()// match 函数匹配可用的中间件列表const resultList = this.match(url, method)this.handle(req, res, resultList)}}listen(...args) {const server = http.createServer(this.callback)server.listen(...args)}}// 工厂函数module.exports = () => {return new LikeExpress()}