Koa2基础(一)

228 阅读6分钟

版本

{
    "koa": "^2.12.0",
    "koa-body": "^4.1.3",
    "koa-json": "^2.0.2",
    "koa-router": "^8.0.8",
    "koa2-cors": "^2.0.6"
}

Koa2基础(一)

koa2是一个基于NodeJs的web框架,可运行web应用和提供API,实现http协议的处理。

和express相比

  • 更加轻量,没有预置的中间件,可根据自己的需求添加中间件
  • 可使用async函数,使异步通过同步的方式表现出来,更加美观清晰

核心概念

  • Koa Application(核心应用程序)
  • Context(上下文)
  • Request(请求)、Response(响应)

Koa2的简单使用

下载

npm install koa --save

使用

首先新建一个文件夹,在文件夹下进行初始化

npm init -y

在文件夹下创建一个index.js文件,并搭建一个简单的服务

// index.js
const Koa = require('koa')
const app = new Koa()

app.use(async ctx => {
  ctx.body = 'Hello World!!'
})

app.listen(3000)

Koa2中间件

koa-router

koa-router是koa的路由中间件,可以指定url路径,指向一个方法,参数是ctx上下文。

下载

npm install koa-router -S

使用

  1. 首先引入koa-router,再new一个router实例,这个实例提供了router的各种方法;
  2. 通过app.use方法对注册router;
  3. 再使用链式操作的方式注册router.allowedMethods()方法拦截路由中没有的请求;
// index.js
const Koa = require('koa')
const Router = require('koa-router')
const app = new Koa()
const router = new Router()

// 注册路由
app.use(router.routes())
.use(router.allowedMethods()) // 拦截器,拦截路由中没有的请求

app.listen(3000)

作为网页路径使用

// index.js
router.get('/', ctx => {
  console.log(ctx)
  console.log(ctx.request)
  ctx.body = 'Hello World!!'
})

router.get('/api', ctx => {
  ctx.body = 'Hello API!!'
})

我们在网页中输入不同的路径,页面返回了不同的文本。

作为接口使用

通常用于编写接口的步骤就是:

  1. 通过ctx获取请求的参数
  2. 连接数据库,获取数据
  3. 处理数据,返回数据给前台

koa-router常用api

allowedMethods()

作为拦截器使用,拦截路由中没有的请求

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

router.prefix(prefix)

设置已经初始化的路由器实例的路径前缀,可用于设置已经初始化的路由器实例的路径前缀

router.prefix(`/blog`)

使用后,当如以下代码的url为 /create 时,实际的路径应该是 /blog/create

router.get('/create', ctx => {
  ctx.body = 'Hello API!!'
})

可通过 http://localhost:3000/blog/create 进行路由的访问。

该api也可同router.use([path], middleware) ,配合session一起使用判断是否有权限访问该页面或者对应的接口

router.use([path], middleware)

路由中间件

使用场景:我们通常需要通过验证用户和用户权限来判定用户是否能使用该接口,如果在每个接口都写一次验证非常麻烦且不好维护。这时我们就需要路由中间件先进行验证,再执行下面操作。

router.use的第一个参数为一个路径或者由多个需要使用中间件的路径组成的数组(需要注意的是,如果路由设置了url前缀,需要在设置前缀后注册中间件,参数中的url不需要设置前缀)。

router.use的第二个参数为函数,函数传递ctx和next两个参数,可通过ctx进行权限验证后,判断是否执行next调用接口。这里特别需要注意的是函数使用next的时候需要添加await,如果不添加,在调用接口前,接口就会返回结果,前台则无法获取到数据。

// this is wrong
app.use(function (ctx, next) {
    ctx.set("Access-Control-Allow-Origin", "*");
    next();
});
// this is right
app.use(async function (ctx, next) {
    ctx.set("Access-Control-Allow-Origin", "*");
    await next();
});

例子

(这个例子用到了ES6的import和export引入方式,后面的内容提供具体的解决方法)

这里可以配合session和router.prefix()一起做一个访问权限验证。

这个方法用于判断当session中有userInfo用户信息时,继续执行找到对应的路由路径,执行方法,返回值。如果没有ctx.session中没有userInfo这个属性时,则判定为无访问权限。

// routers/middleware
export const verifyUser = async (ctx, next) => {
  if (ctx.session.userInfo) {
    await next()
  } else {
    ctx.response.body = { status: 400, msg: '无权限访问' }
  }
}

这是我的博客接口,BlogController存放博客接口的具体实现,这里则是定义博客的请求方式,参考地址见下方。这里可以看到我创建了很多关于博客的接口,然后来分析一下代码的执行:

  1. 首先使用了 router.prefix(/api/blog) 设置了路由前缀,那么现在router实例创建的实际路径则是/api/router/[path]
  2. 通过 router.use(['/create', '/update', '/delete'], verifyUser) 设置是否有权限访问参数中的api,也就是说,创建新博客、更新博客、删除博客是需要登录后,有userInfo用户信息才能访问的接口。因为router已经设置了前缀,所以使用中间件url参数的路径不是 /api/blog/create ,而是 /create 。
// routers/blog 

 // 引入验证登录路由中间件
import { verifyUser } from '../utils/routerMiddleware'
// 引入路由逻辑层
import BlogController from '../controller/blog.js'

router.prefix(`/api/blog`)
router.use(['/create', '/update', '/delete'], verifyUser)

// 获取博客列表
router.get('/list', BlogController.getList)
// 通过id获取博客信息 
router.get('/:id', BlogController.getBlogById)
// 通过用户id获取用户信息 
router.get('/getUserBlogs', BlogController.getUserBlogs)
// 创建新博客
router.post('/create', BlogController.create)
// 修改博客信息
router.put('/update', BlogController.update)
// 删除博客
router.delete('/delete', BlogController.delete)

参考地址:zhuanlan.zhihu.com/p/26216336 如何使用koa2+es6/7打造高质量Restful API

koa-body

处理post请求时,我们会遇到一个问题,无论是node的request对象还是koa的request对象,都没办法解析request的body,我们就需要下载并引入一个解析body的中间件koa-body中间件。

这里我们可以测试一下,首先通过router实例定义一个post请求的接口:

const Router = require('koa-router')
const router = new Router()

router.post('/add', ctx => {
  let { body } = ctx.request
  console.log(body)
})

然后在postman中请求该接口,在body中输入name和age参数,并运行

得到结果:

undefined

可以看到这里面并没有body属性,现在我们下载koa-body中间件并使用

下载

npm install koa-body -S

使用

引入中间件,并通过koa实例app进行中间件注册,这里需要注意的是,koa-body的注册一定要在路由注册之前。

...
const koaBody = require('koa-body')
const Router = require('koa-router')
const router = new Router()

router.post('/add', ctx => {
  let { body } = ctx.request
  console.log(body)
  ctx.body = {
    ...body
  }
})

...
app.use(koaBody())

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

得到结果

{ name: 'panda', age: 18 }

这里需要注意的是:koa还有一个中间件koa-bodyparser与koa-body拥有同样的功能,不要两个同时使用。

koa-cors

用于解决跨域问题。

下载

npm install koa2-cors

使用

...
const cors = require('koa2-cors')

...
app.use(cors())

koa-helmet

提供重要的安全头,提高应用的安全

下载

npm install koa-helmet -S

使用

// app.js
...
const helmet= require('koa-helmet')

...
app.use(helmet())

koa-static

静态文件服务中间件,使用后,我们可以通过url + 静态文件名称引用静态文件

下载

npm install koa-static -S

使用

注册时使用当前目录__dirname + 绝对路径的

// app.js
...
const statics = require('koa-static')

...
app.use(statics(__dirname + '/public'))

测试

在项目文件夹下创建public文件夹,然后放入一张图片,启动服务器,我们就可以通过服务器地址 + /文件访问到public下的静态文件了。