亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 網站 > WEB開發 > 正文

express的router.js源碼分析

2024-04-27 15:09:17
字體:
來源:轉載
供稿:網友

router.js的代碼其實是router/index.js,里面的代碼是exPRess的路由的核心和入口。下面我們看一下重要的代碼。

proto.handle = function handle(req, res, out) { var self = this; debug('dispatching %s %s', req.method, req.url); var search = 1 + req.url.indexOf('?');//搜索參數的位置 var pathlength = search ? search - 1 : req.url.length;//url路徑的長度 var fqdn = req.url[0] !== '/' && 1 + req.url.substr(0, pathlength).indexOf('://'); //如果url不以/開頭,則找出://的位置 var protohost = fqdn ? req.url.substr(0, req.url.indexOf('/', 2 + fqdn)) : ''; //找出協議和主機的值 var idx = 0; var removed = ''; var slashAdded = false; var paramcalled = {}; // store options for OPTIONS request // only used if OPTIONS request var options = []; // middleware and routes var stack = self.stack; // manage inter-router variables var parentParams = req.params; var parentUrl = req.baseUrl || ''; var done = restore(out, req, 'baseUrl', 'next', 'params'); // setup next layer req.next = next; // for options requests, respond with a default if nothing else responds if (req.method === 'OPTIONS') { done = wrap(done, function(old, err) { if (err || options.length === 0) return old(err); sendOptionsResponse(res, options, old); }); } // setup basic req values req.baseUrl = parentUrl; req.originalUrl = req.originalUrl || req.url; next(); function next(err) { var layerError = err === 'route' ? null : err; // remove added slash if (slashAdded) { req.url = req.url.substr(1); slashAdded = false; } // restore altered req.url if (removed.length !== 0) { req.baseUrl = parentUrl; req.url = protohost + removed + req.url.substr(protohost.length); removed = ''; } // no more matching layers if (idx >= stack.length) { setImmediate(done, layerError); return; } // get pathname of request var path = getPathname(req); if (path == null) { return done(layerError); } // find next matching layer var layer; var match; var route; while (match !== true && idx < stack.length) {//idx在是遞增的變量,不需要置0,while的邏輯為在路由棧中找到每個匹配path的layer并且一個個執行 layer = stack[idx++]; match = matchLayer(layer, path); route = layer.route; if (typeof match !== 'boolean') { // hold on to layerError layerError = layerError || match; } if (match !== true) {//沒有匹配 continue; } if (!route) {// // process non-route handlers normally continue; } if (layerError) { // routes do not match with a pending error match = false; continue; } var method = req.method; var has_method = route._handles_method(method);//因為是使用use方法增加的,所以不需要去判斷是否匹配了請求方法 // build up automatic options response if (!has_method && method === 'OPTIONS') { appendMethods(options, route._options()); } // don't even bother matching route if (!has_method && method !== 'HEAD') { match = false; continue; } } // no match if (match !== true) {//找不到匹配的路由,執行執行done return done(layerError); } // store route for dispatch on change if (route) { req.route = route; } // Capture one-time layer values req.params = self.mergeParams ? mergeParams(layer.params, parentParams) : layer.params; var layerPath = layer.path; // this should be done for the layer self.process_params(layer, paramcalled, req, res, function (err) { if (err) { return next(layerError || err); } if (route) { return layer.handle_request(req, res, next); } trim_prefix(layer, layerError, layerPath, path); }); } function trim_prefix(layer, layerError, layerPath, path) { var c = path[layerPath.length]; if (c && '/' !== c && '.' !== c) return next(layerError); // Trim off the part of the url that matches the route // middleware (.use stuff) needs to have the path stripped if (layerPath.length !== 0) { debug('trim prefix (%s) from url %s', layerPath, req.url); removed = layerPath; req.url = protohost + req.url.substr(protohost.length + removed.length); // Ensure leading slash if (!fqdn && req.url[0] !== '/') { req.url = '/' + req.url; slashAdded = true; } // Setup base URL (no trailing slash) req.baseUrl = parentUrl + (removed[removed.length - 1] === '/' ? removed.substring(0, removed.length - 1) : removed); } debug('%s %s : %s', layer.name, layerPath, req.originalUrl); if (layerError) { layer.handle_error(layerError, req, res, next); } else { layer.handle_request(req, res, next); } }};proto.use = function use(fn) { var offset = 0; var path = '/'; // default path to '/' // disambiguate router.use([fn]) if (typeof fn !== 'function') { var arg = fn; while (Array.isArray(arg) && arg.length !== 0) { arg = arg[0]; } // first arg is the path if (typeof arg !== 'function') { offset = 1; path = fn; } } var callbacks = flatten(slice.call(arguments, offset)); if (callbacks.length === 0) { throw new TypeError('Router.use() requires middleware functions'); } for (var i = 0; i < callbacks.length; i++) { var fn = callbacks[i]; if (typeof fn !== 'function') { throw new TypeError('Router.use() requires middleware function but got a ' + gettype(fn)); } // add the middleware debug('use %s %s', path, fn.name || '<anonymous>'); var layer = new Layer(path, { sensitive: this.caseSensitive, strict: false, end: false }, fn); layer.route = undefined; this.stack.push(layer); } return this;};proto.route = function route(path) { var route = new Route(path); var layer = new Layer(path, { sensitive: this.caseSensitive, strict: this.strict, end: true }, route.dispatch.bind(route)); layer.route = route; this.stack.push(layer); return route;//返回該路由對象,讓用戶配置相關的路徑和回調};

1.從use和route函數的代碼中我們知道,這兩個函數存儲路由數據的方式是不一樣的。雖然都是通過往router的stack里累加layer,但use是里的layer對應的回調是傳進來的fn,而route里的layer對應的回調是route的dispatch,并且通過返回route對象,讓用戶配置相關的路徑和回調。

2.handle函數是處理路由的入口,也是核心的代碼,其中的邏輯比較多,我們主要關注一下next函數和里面的while邏輯,while的邏輯主要是在路由的二維數組中(見route分析那章)逐行查找匹配的路由,直到找到一個匹配的路由,如果找到了一個匹配的路由,則暫時停止查找,并且利于idx來記住當前的位置。然后把邏輯轉到layer層中。

3.通過1的分析,我們知道,轉到layer層的時候,可能只是執行一個fn,也可能是執行route對象的dispatch,不過對于router對象來說,這些都是透明的,執行完layer層后,layer層的函數會通過router傳過去的next回到router的next函數邏輯中,然后基于idx位置繼續查找匹配的路由,繼續以上的過程,知道idx等于stack的長度。查找結束。 這里寫圖片描述


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩在线视频观看| 成人写真视频福利网| 91久久久久久久久久久| 国精产品一区一区三区有限在线| 亚洲影视中文字幕| 国产精品成av人在线视午夜片| 九九热精品视频在线播放| 久久久精品久久| 91精品国产91久久久久久久久| 亚洲一区二区在线播放| 亚洲精品第一国产综合精品| 国产丝袜一区视频在线观看| 亚洲色图综合久久| 欧美在线视频观看免费网站| 韩剧1988免费观看全集| 亚洲国产欧美在线成人app| 亚洲欧美制服第一页| 国产精品久久久久久久久久久不卡| 国产精品欧美激情| 欧美性猛交xxxx免费看漫画| 91亚洲精华国产精华| 国产日韩欧美在线| 成人国产精品一区二区| 亚洲国产97在线精品一区| 国产91对白在线播放| 91免费的视频在线播放| 亚洲中国色老太| 精品国产乱码久久久久久虫虫漫画| 欧美日本亚洲视频| 久久精品最新地址| 欧美国产日本高清在线| 中文.日本.精品| www.欧美视频| 97在线看免费观看视频在线观看| 欧美激情国产日韩精品一区18| 国产色婷婷国产综合在线理论片a| 91亚洲国产成人久久精品网站| 国产精品视频网站| 亚洲精品一区二区网址| 欧美在线一级va免费观看| 亚洲天堂成人在线视频| 日韩成人在线视频观看| 一个人看的www欧美| 日韩电影中文字幕av| 国产福利精品av综合导导航| 亚洲欧美国内爽妇网| 亚洲美女免费精品视频在线观看| 亚洲精美色品网站| 日韩网站免费观看高清| 久久99亚洲热视| 欧美日韩不卡合集视频| 久久久精品久久久久| 欧美午夜片在线免费观看| 大荫蒂欧美视频另类xxxx| 麻豆乱码国产一区二区三区| 亚洲aa中文字幕| 日韩精品视频中文在线观看| 久久精品一偷一偷国产| 欧美日韩国内自拍| 亚洲欧美在线免费观看| 久久精品国产亚洲一区二区| 青青草一区二区| 日韩欧美精品网站| 久久99精品国产99久久6尤物| 午夜精品久久17c| 日韩成人中文电影| 欧美国产欧美亚洲国产日韩mv天天看完整| 亚洲第一页中文字幕| 一本一道久久a久久精品逆3p| 色妞欧美日韩在线| 国产免费一区二区三区在线能观看| 日韩欧美中文字幕在线播放| 久久国产精品电影| 欧美精品激情在线观看| 成人黄色网免费| 欧美猛交ⅹxxx乱大交视频| 成人av资源在线播放| 亚洲国产日韩欧美在线动漫| 欧美性猛交xxxx免费看| 日韩av电影中文字幕| 性亚洲最疯狂xxxx高清| 亚洲免费视频在线观看| 久久中文精品视频| 一区二区三区四区在线观看视频| 91中文字幕在线观看| 欧美专区国产专区| 亚洲人线精品午夜| 成人黄色免费片| 国产日韩精品视频| 国产在线999| 欧美性生交xxxxxdddd| 久久中文精品视频| 精品国偷自产在线视频| 91欧美视频网站| 精品国产老师黑色丝袜高跟鞋| 成人黄色片在线| 亚洲精品一区在线观看香蕉| 81精品国产乱码久久久久久| 国产精品亚洲综合天堂夜夜| 久久久久久久久久国产| 日韩欧美在线字幕| 国产精品小说在线| 97视频国产在线| 亚洲欧美视频在线| 欧美精品在线观看91| 国产一区二区三区在线视频| 亚洲国产精品成人精品| 国产视频欧美视频| 美女久久久久久久| 亚洲国产精品视频在线观看| 欧美性xxxx18| 91亚洲国产精品| 日韩视频―中文字幕| 国产精品久久久久久久久久尿| 久久视频中文字幕| 国产精品ⅴa在线观看h| 精品亚洲va在线va天堂资源站| 日韩免费电影在线观看| 91产国在线观看动作片喷水| 亚洲老头老太hd| 亚洲肉体裸体xxxx137| 一个人看的www久久| 久久久91精品| 色偷偷av一区二区三区乱| 日韩高清av在线| 九九热这里只有精品6| 日韩精品极品视频| 国产精品久久久久久久app| 狠狠躁夜夜躁人人爽天天天天97| www.久久草.com| 日韩欧美亚洲范冰冰与中字| 4388成人网| 久久精品国产亚洲精品2020| 亚洲欧美另类中文字幕| 成人午夜在线视频一区| 日韩欧美在线国产| 91精品久久久久久久久久久| 欧美日韩亚洲视频| 欧美—级a级欧美特级ar全黄| 国产一区二区三区网站| 欧美激情亚洲激情| 亚洲第一区中文字幕| 国产一区玩具在线观看| 国产精品免费一区二区三区都可以| 亚洲自拍av在线| 91久久久久久久久久| 欧美日韩国产123| 亚洲欧美国产制服动漫| 亚洲国产精品va在线看黑人动漫| 成人黄色在线播放| 国产精品一区二区性色av| 在线视频亚洲欧美| 亚洲欧美日韩一区二区在线| 91在线观看免费高清完整版在线观看| 狠狠做深爱婷婷久久综合一区| 国产一区二区在线免费| 日本国产一区二区三区| 成人免费网视频| 中文字幕日韩精品在线观看| 成人网欧美在线视频| 成人做爽爽免费视频| 在线观看免费高清视频97| 麻豆乱码国产一区二区三区| 亚洲最大福利视频网|