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 小时前
Node.js 和 Python 的关系
node.js
吴声子夜歌3 小时前
Node.js——Express框架
node.js·express
吴声子夜歌5 小时前
Node.js——异常处理
node.js
FreeBuf_6 小时前
谷歌将Axios npm供应链攻击归因于朝鲜APT组织UNC1069
前端·npm·node.js
阿正的梦工坊7 小时前
pnpm和npm前端包管理工具有什么不同?
前端·npm·node.js
叶半欲缺7 小时前
Node.js 安装教程
node.js
吴声子夜歌7 小时前
Node.js——Web模板引擎
前端·node.js
雪碧聊技术7 小时前
linux下载node.js(这里面已经包含了npm)
npm·node.js
摇滚侠19 小时前
搭建前端开发环境 安装 nodejs 设置淘宝镜像 最简化最标准版本 不使用 NVM NVM 高版本无法安装低版本 nodejs
java·开发语言·node.js
tumeng07111 天前
Node.JS 版本管理工具 Fnm 安装及配置(Windows)
windows·node.js