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...

相关推荐
知否技术5 小时前
为什么nodejs成为后端开发者的新宠?
前端·后端·node.js
谢尔登10 小时前
【Node.js】worker_threads 多线程
node.js
osnet14 小时前
showdoc二次开发
node.js·vue
泯泷15 小时前
「生产必看」在企业环境中正确使用 Node.js 的九大原则
前端·后端·node.js
太阳火神的美丽人生16 小时前
Vant WeApp 开启 NPM 遇到的问题总结
前端·npm·node.js
fishmemory7sec1 天前
Koa2+mongodb项目实战1(项目搭建)
数据库·mongodb·koa
qingshun1 天前
Node 系列之预热知识(1)
node.js
余生H2 天前
前端的全栈混合之路Meteor篇:RPC方法注册及调用
前端·rpc·node.js·全栈
前端 贾公子2 天前
Node.js env 环境变量多种配置方式
node.js
sooRiverling2 天前
VUE 开发——Node.js学习(一)
vue.js·学习·node.js