Guard

当你需要将多个钩子应用到你的应用程序时,不用重复多次钩子,可以使用 guard 来批量添加钩子到你的应用中。

typescript
import { Elysia, t } from 'elysia'

new Elysia()
	.onBeforeHandle(({ query: { name }, status }) => { 
		if(!name) return status(401) 
	}) 
	.onBeforeHandle(({ query: { name } }) => { 
		console.log(name) 
	}) 
	.onAfterResponse(({ responseValue }) => { 
		console.log(responseValue) 
	}) 
	.guard({ 
		beforeHandle: [ 
			({ query: { name }, status }) => { 
				if(!name) return status(401) 
			}, 
			({ query: { name } }) => { 
				console.log(name) 
			} 
		], 
		afterResponse({ responseValue }) { 
			console.log(responseValue) 
		} 
	}) 
	.get(
		'/auth',
		({ query: { name = 'anon' } }) => `Hello ${name}!`,
		{
			query: t.Object({
				name: t.String()
			})
		}
	)
	.get(
		'/profile',
		({ query: { name = 'anon' } }) => `Hello ${name}!`,
		{
			query: t.Object({
				name: t.String()
			})
		}
	)
	.listen(3000)

不仅如此,你还可以使用 guard模式 应用到多个路由上。

typescript
import { Elysia, t } from 'elysia'

new Elysia()
	.guard({
		beforeHandle: [
			({ query: { name }, status }) => {
				if(!name) return status(401)
			},
			({ query: { name } }) => {
				console.log(name)
			}
		],
		afterResponse({ responseValue }) {
			console.log(responseValue)
		},
		query: t.Object({ 
			name: t.String() 
		}) 
	})
	.get(
		'/auth',
		({ query: { name = 'anon' } }) => `Hello ${name}!`,
		{ 
			query: t.Object({ 
				name: t.String() 
			}) 
		} 
	)
	.get(
		'/profile',
		({ query: { name = 'anon' } }) => `Hello ${name}!`,
		{ 
			query: t.Object({ 
				name: t.String() 
			}) 
		} 
	)
	.listen(3000)

这将在同一实例中 guard 被调用之后,将钩子和模式应用到每个路由。

有关更多信息,请参见 Guard

任务

让我们将两种类型的钩子付诸实践。

  1. Authentication

    Let's add a simple authentication middleware to GET "/auth" endpoint using beforeHandle hook. If query `name` is provided, we will let the request pass, otherwise we will return 401 status.

  2. Interceptor Hook

    Now, let's create another endpoint GET "/profile" that has the same logic with authentication. We can refactor our code by using interceptor hook to avoid duplication.

Show answer

我们可以使用 beforeHandle 来拦截请求,返回一个带有 status 方法的响应。

typescript
import { Elysia } from 'elysia'

new Elysia()
	.onBeforeHandle(({ query: { name }, status }) => {
		if(!name) return status(401)
	})
	.get('/auth', ({ query: { name = 'anon' } }) => {
		return `Hello ${name}!`
	})
	.get('/profile', ({ query: { name = 'anon' } }) => {
		return `Hello ${name}!`
	})
	.listen(3000)
  • index.ts