Guard

When you need to apply multiple hook to your application, instead of repeating hook multiple time, you can use guard to bulk add hooks to your application.

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)

Not only that, you can also apply schema to multiple routes using 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)

This will apply hooks and schema to every routes after .guard is called in the same instance.

See Guard for more information.

Assignment

Let's put 2 types of hooks into practice.

  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

We can use beforeHandle to intercept the request before it reaches the handler, and return a response with status method.

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