Koa 中间件使用案例,内附开源项目

Koa 中间件是一个带有 context 和 next 参数的函数,该函数支持 async/await 语法,在中间件中调用 next 函数将代码的执行权交给下一个中间件,中间件的工作被 next() 分为前后两部分,next() 返回一个 Promise 对象。Koa 官方用洋葱模型来解释中间件的调用顺序,如下图所示:

上图的意思是第一个中间件 next() 前面的代码最先执行,next() 后面的代码最后执行。第一个中间件调用 next() 之后第二个中间件开始工作,第二个中间件调用 next() 之后第三个中间件开始工作,第三个中间件是最后一个中间件,它不必调用 next()。当第三个中间件执行完时,第二个中间件 next() 后面的代码开始执行。比如在 Koa 应用中使用了如下的中间件:

ts 复制代码
app.use(async (context, next) => {
    try {
        await next()
    } catch (error: any) {
        context.body = `出错了,${error}`;
    }
})

app.use(async(context, next) => {
    context.set('X-Response-Time', `${new Date().getTime()}`);
    context.set({
        'Access-Control-Allow-Origin':'*',
        'Access-Control-Allow-Methods': 'GET,POST'
    })
    await next()
    console.log('finish')
})

app.use(async (context) => {
    console.log('set body')
    context.body = 'Hello Koa';
})

第一个中间件用于处理错误,它能处理后面的中间件抛出的任何错误,第二个中间件console.log('finish') 会比第三个中间件 console.log('set body') 后执行。

Koa社区拥有众多的中间件,读者可访问 github.com/koajs/koa/w... 查看

@koa/router

@koa/router是Koa的路由中间件,它支持带参数的动态路由、嵌套路由,还支持在路由上使用多个中间件。它的基本用法如下:

ts 复制代码
const app = new Koa()
const router = new Router()
router
    .get('/', (context) => {
        context.body = '我捕获根路径的get请求'
    })
    .get('/user', context => {
        context.body = '我捕获路径是/user的get请求'
    })
    .post('/user', context => {
        context.body = '我捕获路径是/user的post请求'
    })
app
    .use(router.routes())
    .use(router.allowedMethods())

动态路由

动态路由指的是在路径上携带参数,@koa/router 使用 path-to-regexp 将路径字符串转成正则表达式。动态路径的代码如下:

ts 复制代码
router
    .get('/user/:id', (context) => {
        context.body = `我捕获路径是/user/xx形式的的get请求,路径上的参数是${context.params.id}`
    })
    .get('/user/:id/:local', (context) => {
        context.body = `我捕获路径是/user/xx/yy形式的的get请求,路径上的参数是${context.params.id}和${context.params.local}`
    })

嵌套路由

嵌套路由是指在路由中使用路由,前面的示例代码中所有的路由都是平级的,嵌套路由让路由有父子关系,代码如下:

ts 复制代码
const router = new Router()
const studentRouter = new Router()

studentRouter
    .get('/:id', (context) => {
        context.body = `我捕获路径为 /student/xx 形式的 get 请求`
    })

router.use('/student', studentRouter.routes(), studentRouter.allowedMethods())

app
    .use(router.routes())
    .use(router.allowedMethods())

上述代码中 studentRouter 是 router 的子路由,studentRouter 的路径上不必添加 /student 前缀。

在路由上使用多个中间件

使用多个中间件处理匹配到的路径,代码如下:

ts 复制代码
router
    .get('/user/:id', 
    async (context, next) => {
        console.log(context.params.id)
        await next()
    },
    (context) => {
        context.body = `我捕获路径为 /user/xx 形式的 get 请求`
})

上述代码使用两个中间件去处理 /user/:id,这两个中间件有不同的职责。

koa-compress

koa-compress 是一个用于数据压缩的中间件,使用它能够压缩数据提高传输速度,在 @koa/router 的基础上使用 koa-compress 代码如下:

ts 复制代码
import compress from 'koa-compress'

app
    .use(compress({
       // content_type 是 MIME 类型
        filter(content_type) {
            // 当响应的 Content-Type 中包含 text 时才压缩数据
            return /text/i.test(content_type)
        },
	// 当数据大小超过 500 bytes时压缩
        threshold: 500,
    }))
    .use(router.routes())
    .use(router.allowedMethods())

compress 除了可以配置上述代码中的 filter 和 threshold 字段,还有一些其他的配置项,访问github.com/koajs/compr... 查看更多的配置项。

koa-bodyparser

koa-bodyparser 基于 co-body 解析请求体中的数据,比如获取 POST 请求的参数,它支持 json、form、text 和 xml 类型的请求体,不支持 multipart/form-data,解析出的结果以对象的形式保存在 context.request.body 中。用法如下:

ts 复制代码
import bodyParser from 'koa-bodyparser'
router
    .post('/user', context => {
        context.body = context.request.body
    })

// 将 bodyParser 中间件放在第一个位置
app
	.use(bodyParser())
	.use(router.routes())
    	.use(router.allowedMethods())

bodyParser 有多个配置项,访问github.com/koajs/bodyp... 查看配置项详情。

koa-static

koa-static 是一个专门用来响应静态资源的中间件,客户端可能要加载很多静态资源,比如图片、CSS文件、JavaScript 文件等,单独为这些资源配置路由过于繁琐,使用 koa-static 只需要配置一个静态资源的存放目录,就能统一处理静态资源,代码如下:

ts 复制代码
import koaStatic from 'koa-static'
// 这表明静态资源存放在 Node.js 当前的工作目录,
// 访问 http://localhost:3001/package.json 将得到项目根目录的 package.json 文件
// 访问 http://localhost:3001/static/index.css 将得到项目根目录的 /static/index.css文件
app.use(koaStatic(process.cwd())) 

// 这表明静态资源存放在Node.js 当前工作目录下的 static 目录
// 访问 http://localhost:3001/index.css 将得到项目根目录的 /static/index.css文件
app.use(koaStatic(process.cwd() + '/static')) 

koaStatic 接受两个参数,第一个参数是 koa-static 服务的目录,这个目录之外的静态资源不被 koa-static 服务,第二个参数可选,访问github.com/koajs/stati... 查看第二个参数的详情。

@koa/multer

@koa/multer 是一个基于 multer 实现文件上传的中间件,处理 context-type 为multipart/form-data 的请求,能实现单文件上传和多文件上传,它将 FormData 的文本信息保存在 context.request.body 中,将文件信息保存到 context.request.file 或者 context.request.files 中,下面是一个处理单文件上传的示例:

ts 复制代码
import multer from '@koa/multer'
const upload = multer({
	dest: '/uploads' // 指定文件的保存路径
});

// 这个路由用于单文件上传
 router
    .post(
        '/upload', 
        upload.single('file'), // upload 中间件先处理,处理完再进入下一个中间件
        async (context, next) => {
            console.log('文件名:' + context.request.file.filename)
            console.log('文件路径:' + context.request.file.path)
            await next()
        }
    )

上述代码实现了单文件上传,此时文件信息保存在context.request.file中,如果是多文件上传,那么文件信息保存在context.request.files中,访问 github.com/koajs/multe... 了解 @koa/multer 更多详情。

Koa 开源项目

github.com/react-low-c...

相关推荐
你的电影很有趣2 小时前
lesson72:Node.js 安全实战:Crypto-Js 4.2.0 与 Express 加密体系构建指南
javascript·安全·node.js
玩代码2 小时前
使用 nvm(Node Version Manager) 高效管理Node.js
node.js·vue·nvm
api_180079054604 小时前
异步数据采集实践:用 Python/Node.js 构建高并发淘宝商品 API 调用引擎
大数据·开发语言·数据库·数据挖掘·node.js
_孤傲_6 小时前
webpack实现常用plugin
前端·webpack·node.js
小菜摸鱼1 天前
Node.js + vue3 大文件-切片上传全流程(视频文件)
前端·node.js
PaytonD1 天前
LoopBack 2 如何设置静态资源缓存时间
前端·javascript·node.js
许久'1 天前
环境搭建node.js gnvm
node.js
细节控菜鸡1 天前
Webpack 核心知识点详解:proxy、热更新、Loader与Plugin全解析
前端·webpack·node.js
spmcor1 天前
Nest.js 文件分片上传:当大文件来敲门,别慌,我们有“分尸”妙计!
node.js
星空下的曙光2 天前
Node.js crypto模块所有 API 详解 + 常用 API + 使用场景
算法·node.js·哈希算法