偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Node 第二彈:Node 服務(wù)端應(yīng)用路由解析

開(kāi)發(fā) 前端
大家好,我是山月。在上篇文章介紹了 HTTP 報(bào)文及簡(jiǎn)單的服務(wù)端框架要素,如如何接受請(qǐng)求參數(shù)等。這篇文章介紹另一個(gè)常見(jiàn)的主題:路由。

[[410534]]

大家好,我是山月。在上篇文章介紹了 HTTP 報(bào)文及簡(jiǎn)單的服務(wù)端框架要素,如如何接受請(qǐng)求參數(shù)等。這篇文章介紹另一個(gè)常見(jiàn)的主題:路由。

簡(jiǎn)單路由

最簡(jiǎn)單的路由可使用 req.url 進(jìn)行路由分發(fā)不同的邏輯,代碼如下所示。

但是對(duì)于一個(gè)非Demo式的頁(yè)面,業(yè)務(wù)邏輯都堆在一起,這顯得太為簡(jiǎn)陋。

  1. const http = require('http'
  2.  
  3. const server = http.createServer((req, res) => { 
  4.   console.log(req.url) 
  5.  
  6.   let data = '' 
  7.   if (req.url === '/') { 
  8.     data = 'hello, world' 
  9.     res.end(data) 
  10.   } else if (req.url === '/json') { 
  11.     res.setHeader('Content-Type''application/json; charset=utf-8'); 
  12.     data = JSON.stringify({ username: '山月' }) 
  13.     res.end(data) 
  14.   } else if (req.url === '/input') { 
  15.     let body = '' 
  16.     req.on('data', chunk => body += chunk) 
  17.     req.on('end', () => { 
  18.       data = body 
  19.       res.end(data) 
  20.     }) 
  21.   } 
  22.    
  23. }) 
  24.  
  25. server.listen(3000) 

復(fù)雜路由

作為一個(gè)能夠在生產(chǎn)環(huán)境使用,較為復(fù)雜的路由至少能夠解析以下路由,并為單獨(dú)路由配置單獨(dú)的業(yè)務(wù)邏輯處理函數(shù)

  1. Method: app.post('/', handler) 
  2. Param Path: app.post('/users/:userId', handler) 

基于正則路由

目前,絕大部分服務(wù)端框架的路由都是基于正則進(jìn)行匹配,如 koa、express 等。另外,前端框架的路由 vue-router 與 react-router 也是基于正則匹配。

而這些框架基于正則匹配的路由,都離不開(kāi)一個(gè)庫(kù): path-to-regexp,它將把一個(gè)路由如 /user/:name 轉(zhuǎn)化為正則表達(dá)式。

https://github.com/pillarjs/path-to-regexp

標(biāo)題:path-to-regexp

它的 API 十分簡(jiǎn)單:

  • pathToRegexp: 可將路由轉(zhuǎn)化為正則表達(dá)式
  • match: 可匹配參數(shù)
  1. const { pathToRegexp, match, parse, compile } = require('path-to-regexp'
  2.  
  3. pathToRegexp('/api/users/:userId'
  4. //=> /^\/api\/users(?:\/([^\/#\?]+?))[\/#\?]?$/i 
  5.  
  6.  
  7. const toParams = match('/api/users/:userId'
  8. toParams('/api/users/10'
  9. //=> { 
  10. //   index: 0 
  11. //   params: {userId: "12"
  12. //   path: "/api/users/12" 
  13. // } 

那這些 Node 服務(wù)器框架基于正則路由的原理是什么?

  • 注冊(cè)路由。每一個(gè)路由都作為一個(gè) Layer (在 express、koa 中),并使用 path-to-regexp 把路由路徑轉(zhuǎn)化為正則,作為 Layer 的屬性。
  • 匹配路由。當(dāng)一次請(qǐng)求來(lái)臨時(shí),對(duì)比路由表中每一條路由,找到匹配正則的多條路由,執(zhí)行多條路由所對(duì)應(yīng)的業(yè)務(wù)處理邏輯。

從上可以看出它沒(méi)進(jìn)行一次路由匹配的時(shí)間復(fù)雜度為: 「O(n) X 正則匹配復(fù)雜度」

基于正則路由的一些問(wèn)題

性能問(wèn)題先不談,先看一個(gè)問(wèn)題:

「當(dāng)我們請(qǐng)求 /api/users/10086,有兩條路由可供選擇: /api/users/10086 與 /api/users/:userId,此時(shí)將會(huì)匹配哪一條路由?」

以下是由 koa/koa-router 書(shū)寫(xiě), 「由于是正則匹配,此時(shí)極易出現(xiàn)路由沖突問(wèn)題,匹配路由時(shí)與順序極為相關(guān)。」

  1. const Koa = require("koa"); 
  2. const Router = require("@koa/router"); 
  3.  
  4. const app = new Koa(); 
  5. const router = new Router(); 
  6.  
  7. router.get("/api/users/10086", (ctx, next) => { 
  8.   console.log(ctx.router); 
  9.   ctx.body = { 
  10.     userId: 10086, 
  11.     direct: true 
  12.   }; 
  13. }); 
  14.  
  15. router.get("/api/users/:userId", (ctx, next) => { 
  16.   console.log(ctx.router); 
  17.   ctx.body = { 
  18.     userId: ctx.params.userId 
  19.   }; 
  20. }); 

基于前綴樹(shù)路由 (Trie、Radix Tree、Prefix Tree)

相對(duì)于正則匹配路由而言,基于前綴樹(shù)匹配更加高效,且無(wú)上述路由沖突問(wèn)題。

  • find-my-way

https://github.com/delvedor/find-my-way

標(biāo)題:find-my-way

  1. const http = require('http'
  2. const router = require('find-my-way')() 
  3.  
  4. const server = http.createServer((req, res) => { 
  5.   router.lookup(req, res) 
  6. }) 
  7.  
  8. router.on('GET''/api', () => {}) 
  9. router.on('GET''/api/users/:id', (req, res) => { res.end('id') }) 
  10. router.on('GET''/api/users/10086', (req, res) => { res.end('10086') }) 
  11. router.on('GET''/api/users-friends', () => {}) 
  12.  
  13. console.log(router.prettyPrint()) 
  14.  
  15. server.listen(3000) 

在上述代碼中,將把所有路由路徑構(gòu)成前綴樹(shù)。前綴樹(shù),顧名思義,將會(huì)把字符串的公共前綴提取出來(lái)。

  1. └── /api (GET) 
  2.     └── /users 
  3.         ├── / 
  4.         │   ├── 10086 (GET) 
  5.         │   └── :id (GET) 
  6.         └── -friends (GET) 

可以看出,前綴樹(shù)路由的匹配時(shí)間復(fù)雜度明顯小于 O(n),且每次不會(huì)有正則路由進(jìn)行正則匹配的復(fù)雜度。這決定了它相比正則路由更高的性能。

Node 中最快的框架 fastify,便是內(nèi)置了基于前綴樹(shù)的路由。

  1. const fastify = require('fastify')() 
  2.  
  3. fastify.get('/api/users/10086', async (request, reply) => { 
  4.   return { userId: 10086, direct: true } 
  5. }) 
  6.  
  7. fastify.get('/api/users/:id', async (request, reply) => { 
  8.   const id = request.params.id 
  9.   return { userId: id } 
  10. }) 
  11.  
  12. fastify.listen(3000) 

405

在 HTTP 狀態(tài)碼中,與路由相關(guān)的狀態(tài)碼為 404、405,作為一個(gè)專業(yè)的路由庫(kù),實(shí)現(xiàn)一個(gè) 405 也是分內(nèi)之事。

  • 301
  • 302
  • 307
  • 308
  • 404: Not Found
  • 405: Method Not Allowed
嗯,代碼就不放了...
本文轉(zhuǎn)載自微信公眾號(hào)「全棧成長(zhǎng)之路」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系全棧成長(zhǎng)之路公眾號(hào)。

 

責(zé)任編輯:武曉燕 來(lái)源: 全棧成長(zhǎng)之路
相關(guān)推薦

2016-09-18 16:04:24

HTTPNode應(yīng)用

2017-10-31 10:32:44

2017-09-07 12:35:39

前端JavascriptNode.js

2024-02-01 12:12:01

2010-08-03 09:59:30

NFS服務(wù)

2016-10-18 16:45:20

JavaScript移動(dòng)服務(wù)端

2022-05-10 08:11:47

VercelNode 服務(wù)

2021-09-06 09:46:26

Dubbo 服務(wù)端開(kāi)發(fā)

2020-12-28 08:48:44

JS工具fastify

2016-03-18 09:04:42

swift服務(wù)端

2012-10-16 09:33:18

iOS最年輕開(kāi)發(fā)者

2021-09-02 10:49:25

Node.jsPHP服務(wù)器開(kāi)發(fā)

2021-06-12 18:37:56

Nodejs前端開(kāi)發(fā)

2011-07-26 11:07:08

JavaScript

2024-06-05 08:42:24

2020-04-29 21:54:46

操作系統(tǒng)核心概念

2010-10-14 14:58:36

SUSE Linux

2020-08-28 13:27:25

Docker Node應(yīng)用

2012-03-02 10:38:33

MySQL

2013-03-25 10:08:44

PHPWeb
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)