1. // 中间件的概念 控制是否向下执行 (权限处理)
    2. // 中间件 可以扩展 req 和 res中的方法
    3. // 中间件 一般放在路由之前
    4. // 中间件 可以提前处理一些逻辑 和 koa 用法一样
    5. // express 中间 如果路由 完全匹配 、 以中间件路径开头 或者路径是/ 都可以匹配到
    6. const express = require('./express');
    7. const app = express();
    8. // express 中的中间件可以放置路径 这个路径的规则 和 cookie中path的一样 {path:'/a'} /
    9. app.use(function (req,res,next) {
    10. req.a = 1;
    11. next();
    12. })
    13. app.use('/',function (req, res, next) {
    14. req.a++;
    15. next();
    16. })
    17. app.use('/a', function (req, res, next) {
    18. req.a++;
    19. next();
    20. })
    21. app.get('/a',function (req,res,next) {
    22. res.end(req.a + '')
    23. })
    24. app.get('/', function (req, res, next) {
    25. res.end(req.a + '')
    26. })
    27. app.listen(3000);
    1. const url = require('url');
    2. const Route = require('./route');
    3. const Layer = require('./layer');
    4. const methods = require('methods');
    5. function Router(){
    6. this.stack = [];
    7. }
    8. Router.prototype.route = function (path) {
    9. let route = new Route();
    10. let layer = new Layer(path,route.dispatch.bind(route)); // 给当前调用get方法 放入一层
    11. layer.route = route; // 每个层都有一个route属性 标识他是一个路由
    12. this.stack.push(layer);
    13. return route;
    14. }
    15. Router.prototype.use = function (path,handler) { // 中间件 会放到当前的路由系统中
    16. if(typeof path === 'function'){
    17. handler = path; // 给path默认值
    18. path = '/'
    19. }
    20. let layer = new Layer(path,handler); // 产生一层
    21. layer.route = undefined; // 如果route是undefind 说明他是中间件
    22. this.stack.push(layer);
    23. }
    24. methods.forEach(method=>{
    25. Router.prototype[method] = function (path, handlers) { // 用户调用get方法时 传递了多个处理函数
    26. let route = this.route(path); // 构建一个route的
    27. route[method](handlers); // 交给route 来存储用户的真正的handler
    28. }
    29. })
    30. Router.prototype.handle = function (req,res,out) {
    31. // 请求到来时 开始出路请求
    32. let {pathname} = url.parse(req.url); // 获取请求来的路径
    33. let idx = 0;
    34. let dispatch =() => { // express 需要通过next函数来迭代
    35. if (idx === this.stack.length) return out(); // 如果路由处理不了 交给application处理
    36. let layer = this.stack[idx++];
    37. // 路由 、 中间件 必须要求 路径匹配才ok
    38. if (layer.match(pathname)) { // layer有可能是中间 还有可能是路由
    39. if(!layer.route){ // 如果是中间件 直接执行 对应的方法即可
    40. layer.handle_request(req, res, dispatch);
    41. }else{
    42. if (layer.route.methods[req.method.toLowerCase()]){
    43. layer.handle_request(req, res, dispatch);
    44. }else{
    45. dispatch();
    46. }
    47. }
    48. }else{
    49. dispatch();
    50. }
    51. }
    52. dispatch();
    53. }
    54. module.exports = Router;
    1. const http = require('http');
    2. const url = require('url');
    3. const path = require('path');
    4. const Router = require('./router');
    5. const methods = require('methods');
    6. function Application() { // 路由的配置 应该归属 应用来管理
    7. }
    8. Application.prototype.lazy_route = function () {
    9. if(!this._router){
    10. // 把应用和路由分离
    11. this._router = new Router(); // 默认一调用express()
    12. }
    13. }
    14. Application.prototype.use = function (path,handler) {
    15. this.lazy_route();
    16. this._router.use(path, handler)
    17. }
    18. // get post delete
    19. methods.forEach(method=>{
    20. Application.prototype[method] = function (path, ...handlers) {
    21. this.lazy_route();
    22. this._router[method](path, handlers)
    23. }
    24. })
    25. Application.prototype.listen = function () {
    26. let server = http.createServer( (req, res) => {
    27. // 获取请求的方法
    28. // 应用提供一个找不到的方法 如果路由内部无法匹配 调用此方法即可
    29. function done(){
    30. res.end(`Cannot ${req.method} ${req.url}`)
    31. }
    32. this.lazy_route();
    33. this._router.handle(req,res,done)
    34. });
    35. server.listen(...arguments)
    36. }
    37. module.exports = Application;
    1. // 每次存储时一个对象
    2. function Layer(path,handler){
    3. this.path = path;
    4. this.handler = handler;
    5. }
    6. Layer.prototype.match = function (pathname) { // /a/b
    7. if (this.path === pathname){
    8. return true
    9. }
    10. // 如果是中间件 要特殊处理
    11. if(!this.route){
    12. // 说明是中间件
    13. if(this.path === '/'){
    14. return true;
    15. }
    16. return pathname.startsWith(this.path+'/')
    17. }
    18. }
    19. Layer.prototype.handle_request = function (req,res,next) {
    20. this.handler(req,res,next);
    21. }
    22. module.exports = Layer;
    1. // 每个层 都有一个route属性
    2. const Layer = require('./layer');
    3. const methods = require('methods');
    4. function Route(){
    5. this.stack = [];
    6. // 用于 匹配路径的时候 加速匹配,如果没有此方法的处理 直接跳过即可
    7. this.methods = {}; // 他表示当前route中有哪些方法 {get:true,post:true}
    8. }
    9. Route.prototype.dispatch = function (req,res,out) {
    10. let idx = 0;
    11. let method = req.method.toLowerCase(); // 获取请求的方法
    12. let dispatch = ()=>{
    13. console.log('inner')
    14. if (idx === this.stack.length) return out();
    15. let layer = this.stack[idx++];
    16. if (layer.method === method){ // 获取内部的第一层 看下是否方法匹配
    17. layer.handle_request(req, res, dispatch)
    18. }else{
    19. dispatch();
    20. }
    21. }
    22. dispatch();
    23. }
    24. methods.forEach(method => {
    25. Route.prototype[method] = function (handlers) {
    26. handlers.forEach(handler => {
    27. let layer = new Layer('/', handler);
    28. layer.method = method; // 用户调用什么方法 存入method就是什么
    29. this.methods[method] = true; // 如果用户绑定方法 我就记录一下
    30. this.stack.push(layer);
    31. });
    32. }
    33. });
    34. module.exports = Route;