Skip to content

错误处理

¥Error Handling

本页提供更高级的指南,帮助你有效地使用 Elysia 处理错误。

¥This page provide a more advance guide for effectively handling errors with Elysia.

如果你还没有阅读 "生命周期 (onError)",我们建议你先阅读它。

¥If you haven't read "Life Cycle (onError)" yet, we recommend you to read it first.

自定义验证消息

¥Custom Validation Message

定义架构时,可以为每个字段提供自定义验证消息。

¥When defining a schema, you can provide a custom validation message for each field.

当验证失败时,此消息将按原样返回。

¥This message will be returned as-is when the validation fails.

ts
import { Elysia } from 'elysia'

new Elysia().get('/:id', ({ params: { id } }) => id, {
    params: t.Object({
        id: t.Number({
            error: 'id must be a number'
        })
    })
})

如果 id 字段验证失败,则返回结果为 id must be a number

¥If the validation fails on the id field, the response will be return as id must be a number.

localhost

GET

验证详情

¥Validation Detail

schema.error 返回值将按原样返回验证,但有时你可能还希望返回验证详细信息,例如字段名称和预期类型。

¥Returning as value from schema.error will return the validation as-is, but sometimes you may also want to return the validation details, such as the field name and the expected type

你可以使用 validationDetail 选项执行此操作。

¥You can do this by using the validationDetail option.

ts
import { Elysia, validationDetail } from 'elysia'

new Elysia().get('/:id', ({ params: { id } }) => id, {
    params: t.Object({
        id: t.Number({
            error: validationDetail('id must be a number') 
        })
    })
})

这将在响应中包含所有验证详细信息,例如字段名称和预期类型。

¥This will include all of the validation details in the response, such as the field name and the expected type.

localhost

GET

但如果你计划在每个字段中使用 validationDetail,手动添加它会很麻烦。

¥But if you're planned to use validationDetail in every field, adding it manually can be annoying.

你可以通过在 onError 钩子中处理来自动添加验证详细信息。

¥You can automatically add validation detail by handling it in onError hook.

ts
new Elysia()
    .onError(({ error, code }) => {
        if (code === 'VALIDATION') return error.detail(error.message) 
    })
    .get('/:id', ({ params: { id } }) => id, {
        params: t.Object({
            id: t.Number({
                error: 'id must be a number'
            })
        })
    })
    .listen(3000)

这将为每个验证错误应用自定义验证消息。

¥This will apply every validation error with a custom message with custom validation message.

生产环境中的验证详情

¥Validation Detail on production

默认情况下,如果 NODE_ENVproduction,Elysia 将省略所有验证细节。

¥By default, Elysia will omitted all validation detail if NODE_ENV is production.

这样做是为了防止泄露有关验证模式的敏感信息,例如字段名称和预期类型,这些信息可能被攻击者利用。

¥This is done to prevent leaking sensitive information about the validation schema, such as field names and expected types, which could be exploited by an attacker.

Elysia 将仅返回验证失败,不提供任何详细信息。

¥Elysia will only return that validation failed without any details.

json
{
    "type": "validation",
    "on": "body",
    "found": {},
    // Only shown for custom error
    "message": "x must be a number"
}

message 属性是可选的,默认情况下会省略,除非你在架构中提供自定义错误消息。

¥The message property is optional and is omitted by default unless you provide a custom error message in the schema.

自定义错误

¥Custom Error

Elysia 在类型级别和实现级别都支持自定义错误。

¥Elysia supports custom error both in the type-level and implementation level.

默认情况下,Elysia 具有一组内置错误类型,例如 VALIDATIONNOT_FOUND,它们会自动缩小类型范围。

¥By default, Elysia have a set of built-in error types like VALIDATION, NOT_FOUND which will narrow down the type automatically.

如果 Elysia 不知道错误,错误代码将为 UNKNOWN,默认状态为 500

¥If Elysia doesn't know the error, the error code will be UNKNOWN with default status of 500

但是,你也可以使用 Elysia.error 添加具有类型安全性的自定义错误,这将有助于缩小错误类型范围,从而实现完全类型安全性和自动补齐功能,并自定义状态代码,如下所示:

¥But you can also add a custom error with type safety with Elysia.error which will help narrow down the error type for full type safety with auto-complete, and custom status code as follows:

typescript
import { 
Elysia
} from 'elysia'
class
MyError
extends
Error
{
constructor(public
message
: string) {
super(
message
)
} } new
Elysia
()
.
error
({
MyError
}) .
onError
(({
code
,
error
}) => {
switch (
code
) {
// With auto-completion case 'MyError': // With type narrowing // Hover to see error is typed as `CustomError` return
error
} }) .
get
('/:id', () => {
throw new
MyError
('Hello Error')
})

自定义状态码

¥Custom Status Code

你还可以通过在自定义错误类中添加 status 属性,为自定义错误提供自定义状态代码。

¥You can also provide a custom status code for your custom error by adding status property in your custom error class.

typescript
import { Elysia } from 'elysia'

class MyError extends Error {
    status = 418

    constructor(public message: string) {
        super(message)
    }
}

Elysia 将在抛出错误时使用此状态码。

¥Elysia will then use this status code when the error is thrown.

或者,你也可以在 onError 钩子中手动设置状态码。

¥Otherwise you can also set the status code manually in the onError hook.

typescript
import { Elysia } from 'elysia'

class MyError extends Error {
	constructor(public message: string) {
		super(message)
	}
}

new Elysia()
	.error({
		MyError
	})
	.onError(({ code, error, status }) => {
		switch (code) {
			case 'MyError':
				return status(418, error.message)
		}
	})
	.get('/:id', () => {
		throw new MyError('Hello Error')
	})

自定义错误响应

¥Custom Error Response

你还可以在自定义错误类中提供自定义 toResponse 方法,以便在抛出错误时返回自定义响应。

¥You can also provide a custom toResponse method in your custom error class to return a custom response when the error is thrown.

typescript
import { Elysia } from 'elysia'

class MyError extends Error {
	status = 418

	constructor(public message: string) {
		super(message)
	}

	toResponse() {
		return Response.json({
			error: this.message,
			code: this.status
		}, {
			status: 418
		})
	}
}

抛出或返回

¥To Throw or Return

Elysia 中的大多数错误处理可以通过抛出错误来完成,并将在 onError 中处理。

¥Most of an error handling in Elysia can be done by throwing an error and will be handle in onError.

status 可能会有点令人困惑,因为它既可以用作返回值,也可以抛出错误。

¥But for status it can be a little bit confusing, since it can be used both as a return value or throw an error.

它可以根据你的具体需求返回或抛出异常。

¥It could either be return or throw based on your specific needs.

  • 如果抛出 status 异常,它将被 onError 中间件捕获。

  • 如果返回的是 status,它将不会被 onError 中间件捕获。

参见以下代码:

¥See the following code:

typescript
import { Elysia, file } from 'elysia'

new Elysia()
    .onError(({ code, error, path }) => {
        if (code === 418) return 'caught'
    })
    .get('/throw', ({ status }) => {
        // This will be caught by onError
        throw status(418)
    })
    .get('/return', ({ status }) => {
        // This will NOT be caught by onError
        return status(418)
    })
localhost

GET