中间件
中间件是请求尚未到达路由处理程序之前的一系列函数。
函数链中的每一个中间件函数都有能力结束请求或通过 next
转发这个请求到下一个中间件函数。
基础例子
添加一个中间件最简单的方式是使用Route.middleware
方法直接附加在路由上。例如:
Route
.get('/users/:id', async () => {
return 'Show user'
})
// highlight-start
.middleware(async (ctx, next) => {
console.log(`Inside middleware ${ctx.request.url()}`)
await next()
})
// highlight-end
中间件类
在某些需要快速测试的情况下,内联函数是一个不错的方式。但是,我们建议将中间件提取到单独的文件中。您可以通过运行以下Ace命令,创建一个新的中间件。
node ace make:middleware LogRequest
# CREATE: app/Middleware/LogRequest.ts
关于中间件类
中间件类文件存储在app/Middleware
文件夹下(不是必须的),每个文件都代表一个单独的中间件。
中间件必须实现 handle
方法用于处理请求,并且调用next
方法转发请求到下一个中间件,或路由处理程序。
// title: app/Middleware/LogRequest.ts
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class LogRequest {
public async handle(
{ request }: HttpContextContract,
next: () => Promise<void>
) {
console.log(`-> ${request.method()}: ${request.url()}`)
await next()
}
}
你也可以在中间件中,抛出异常终止请求。 或者使用response.send
方法响应请求。
注:当你想结束请求时候,不要调用
next
方法。
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class Auth {
public async handle(
{ request, response }: HttpContextContract,
next: () => Promise<void>
) {
if (notAuthenticated) {
response.unauthorized({ error: 'Must be logged in' })
return
}
await next()
}
}
注册中间件
为了让中间件生效,你必须在start/kernel.ts
文件中,将它注册为 全局中间件 或者一个 命名中间件。
全局中间件
全局中间件,是一个中间件队列。中间件会按照他们注册的顺序,一个个的处理HTTP请求。
你在start/kernel.ts
文件中注册中间件时,就想下面一样注册:
// title: start/kernel.ts
Server.middleware.register([
() => import('@ioc:Adonis/Core/BodyParser'),
// highlight-start
() => import('App/Middleware/LogRequest')
// highlight-end
])
命名中间件
命名中间件允许你选择性的在路由组或单个路由中,使用你的中间件。
首先用唯一的名称注册它们,然后在路由上引用它。
// title: start/kernel.ts
Server.middleware.registerNamed({
auth: () => import('App/Middleware/Auth')
})
现在,你可以将auth
中间件,挂载到路由中。如下:
Route
.get('dashboard', 'DashboardController.index')
.middleware('auth') // 👈
中间件可以用于资源路由的一个或多个操作。学习更多 applying middleware to resourceful routes.
您还可以将它们作为数组或多次调用中间件,用这种方式挂载多个中间件。
Route
.get('dashboard', 'DashboardController.index')
.middleware(['auth', 'acl', 'throttle'])
Route
.get('dashboard', 'DashboardController.index')
.middleware('auth')
.middleware('acl')
.middleware('throttle')
将配置传递给指定中间件
命名中间件也可以通过handle
方法的第三个参数,在运行时接受配置参数,例如:
export default class Auth {
public async handle(
{ request, response }: HttpContextContract,
next: () => Promise<void>,
// highlight-start
guards?: string[]
// highlight-end
) {
await next()
}
}
上例中,Auth 中间件接收一个可选的 guards
数组。中间件用户可以这样传入 guards:
Route
.get('dashboard', 'DashboardController.index')
.middleware('auth:web,api')
FAQs
怎样让给定的 HTTP 请求禁用中间件?
你不能让指定的 HTTP 请求禁用中间件。不过,中间件可以通过接收一个运行时配置,来忽略特定请求。
以 bodyparser 中间件为例。它[忽视不能匹配白名单方法的所有请求](https://github.com/adonisjs/bodyparser/blob/develop/src/BodyParser/index.ts#L108-L111),这些白名单方法在 `config/bodyparser.ts` 文件中定义。
中间件是否在没有路由的请求中执行?
如果当前的 HTTP 请求没有注册路由,AdonisJS 不会执行中间件。
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。