Koa 路由中間件原理及使用技巧

本文主要是爲了介紹路由的做用,以及在 Koa 路由中間件的使用,一些高級用法,和實用技巧等

什麼是路由?

  • 處理不一樣的 URL
  • 處理不一樣的 HTTP 方法 (GETPOSTPUTDELETEPATCHOPTIONS)
  • 解析 URL 上的參數

HTTP 協議而言,路由能夠理解爲,根據不一樣的 HTTP 請求,返回不一樣的響應;node

若是沒有路由會怎麼樣?請看下面的代碼:json

const Koa = require('koa')
const app = new Koa()

app.use(async ctx => {
  ctx.body = 'hello world'
})

app.listen(3000)

經過 Postman 訪問 3000 端口,不管是何種 HTTP 方法,仍是不一樣的 URL 都將返回相同的內容 app

這種沒有路由WEB服務,幾乎作不了什麼有價值的事情koa

自定義 Koa 路由中間件

路由,最基本的功能就是能夠處理不一樣的 URL, 不一樣的 HTTP方法, 以及解析 URL 參數

處理不一樣的 HTTP 方法

const Koa = require('koa')
const app = new Koa()

app.use(async ctx => {
  if (ctx.method === 'GET') {
    ctx.body = 'GET 請求'
  } else if (ctx.method === 'POST') {
    ctx.body = 'POST 請求'
  } else if (ctx.method === 'PUT') {
    ctx.body = 'PUT 請求'
  } else if (ctx.method === 'DELETE') {
    ctx.body = 'DELETE 請求'
  }
})

app.listen(3000)

處理不一樣的 URL

app.use(async ctx => {
  if (ctx.method === 'GET') {
    switch (ctx.url) {
      case '/': ctx.body = '首頁'; break;
      case '/users': ctx.body = '用戶列表'; break;
      case '/articles': ctx.body = '文章列表'; break;
      default: ctx.status = 404
    }
  }
})

解析 URL 參數

app.use(async ctx => {
  if (ctx.method === 'GET') {
    // 根據用戶 ID 獲取用戶信息
    if (/^\/users\/(\w+)$/.test(ctx.url)) {
      return ctx.body = `用戶 ID 爲: ${RegExp.$1}`
    }
    ctx.status = 404
  }
})

上面的演示代碼只是最最基本的路由概念,完整的路由邏輯實際須要考慮的狀況更加複雜async

建議

一個優秀、優雅的程序,須要獨立維護的代碼越少越好,千萬不要乾重復造輪子的事情,生命有限!使用官方的中間件,或者其它第三方優秀的中間件,能夠節省開發時間,提升開發效率!

koa-router

koa-router 的基本使用

安裝

yarn add koa-router

基本使用

const Koa = require('koa');
const Router = require('koa-router');

const app = new Koa();
const router = new Router();

// 處理不一樣的 HTTP 方法
router
  .get('/users', ctx => {
    ctx.body = '獲取用戶列表'
  })
  .post('/users', ctx => {
    ctx.body = '建立用戶'
  })
  .put('/users/:id', ctx => {
    // 解析 URL 參數
    ctx.body = `更新 ID 爲 ${ctx.params.id} 的用戶`
  })
  .delete('/users/:id', ctx => {
    // 解析 URL 參數
    ctx.body = `刪除 ID 爲 ${ctx.params.id} 的用戶`
  })

// 註冊路由中間件
app.use(router.routes())

app.listen(3000)

路由前綴

配置 koa-router 的路由前綴,實現路由分類
const Koa = require('koa');
const Router = require('koa-router');

const app = new Koa();

const articleRouter = new Router({ prefix: '/articles' }) // 文章接口
const userRouter = new Router({ prefix: '/users' }) // 用戶接口

articleRouter.get('/', ctx => ctx.body = '文章列表')
userRouter.get('/', ctx => ctx.body = '用戶列表')

app.use(articleRouter.routes())
app.use(userRouter.routes())

app.listen(3000)

使用 koa-routerallowedMethods 方法, 能夠實現 HTTPOPTIONS方法請求

OPTIONS 請求能夠檢測接口所支持的請求方法

假若有以下代碼,經過 userRouter.allowedMethods() 中間件,讓 /users 接口實現 options 方法post

const Koa = require('koa');
const Router = require('koa-router');

const app = new Koa();

const userRouter = new Router({ prefix: '/users' }) // 用戶接口

userRouter.get('/', ctx => ctx.body = '用戶列表')
userRouter.post('/', ctx => ctx.body = '建立用戶')
userRouter.put('/:id', ctx => ctx.body = ctx.params.id)

// 使用了 userRouter.allowedMethods() 中間件,讓 /users 接口實現 options 方法
app.use(userRouter.routes()).use(userRouter.allowedMethods())

app.listen(3000)

使用 postman 測試 OPOTIONS 方法測試

2020-03-23_013731.jpg

響應頭信息中的 ALLOW 字段中,顯示了 /users 接口支持的 HTTP 方法有 GETPOSTPUT ui

若是 OPTIONS 方法請求接口沒有實現的 HTTP 方法,將會返回 405 的狀態碼url

2020-03-23_014618.jpg

若是 OPTIONS 方法請求 HTTP 不支持的方法,將會返回 501 的狀態碼spa

2020-03-23_014835.jpg

koa 多路由註冊的技巧

在實際的項目中,咱們的接口是多種多樣的,不可能在入口文件中定義所有路由

建立 routes 文件夾,存放全部不一樣的路由接口

├── routes (路由)
│ └── articles.js
│ └── users.js
│ └── index.js

├── index.js (入口)

└── package.json

// routes/articles.js  

const Router = require('koa-router')
const router = new Router({ prefix: '/articles' })

router.get('/', ctx => ctx.body = '文章列表')

module.exports = router
// routes/users.js  

const Router = require('koa-router')
const router = new Router({ prefix: '/users' })

router.get('/', ctx => ctx.body = '文章列表')

module.exports = router
// routes/index.js  

const fs = require('fs');
module.exports = (app) => {
  // 使用 fs 模塊自動讀取並註冊 routes 文件夾下全部路由接口
  fs.readdirSync(__dirname).forEach(file => {
    if (file === 'index.js') { return; }
    const route = require(`./${file}`);
    app.use(route.routes()).use(route.allowedMethods());
  });
}
const Koa = require('koa');
const app = new Koa();
const routing = require('./routes');

// 一次性註冊路由
routing(app)

app.listen(3000)
相關文章
相關標籤/搜索