fontcolor_theme
Deepkit HTTP

事件

HTTP 模块基于一个工作流引擎,该引擎提供了多种事件令牌,可用于挂接到处理 HTTP 请求的整个流程中。

该工作流引擎是一个有限状态机,会为每个 HTTP 请求创建一个新的状态机实例,然后在各个位置之间跳转。第一个位置是 start,最后一个是 response。在每个位置都可以执行附加代码。

每个事件令牌都有其自己的事件类型,并附带额外信息。

httpWorkflow.onRequest当有新请求进来时
httpWorkflow.onRoute当需要从请求解析路由时
httpWorkflow.onRouteNotFound当未找到路由时
httpWorkflow.onAuth当进行身份验证时
httpWorkflow.onResolveParameters当解析路由参数时
httpWorkflow.onAccessDenied当访问被拒绝时
httpWorkflow.onController当调用控制器动作时
httpWorkflow.onControllerError当控制器动作抛出错误时
httpWorkflow.onParametersFailed当解析路由参数失败时
httpWorkflow.onResponse当控制器动作已被调用时。此处将结果转换为响应。

由于所有 HTTP 事件都基于工作流引擎,可以使用指定的事件并通过 event.next() 方法跳转,从而修改其行为。

HTTP 模块在这些事件令牌上使用了自身的事件监听器来实现 HTTP 请求处理。所有这些事件监听器的优先级为 100,这意味着当你监听某个事件时,你的监听器默认会先执行(因为默认优先级是 0)。将优先级设为高于 100 可在 HTTP 默认处理器之后运行。

例如,假设你想拦截控制器被调用时的事件。如果将要调用某个特定控制器,我们检查用户是否有访问权限。若有,则继续;若没有,则跳转到下一个工作流项 accessDenied。在那里,访问被拒绝的处理流程会被自动继续执行。

import { App } from '@deepkit/app';
import { FrameworkModule } from '@deepkit/framework';
import { HtmlResponse, http, httpAction, httpWorkflow } from '@deepkit/http';
import { eventDispatcher } from '@deepkit/event';

class MyWebsite {
    @http.GET('/')
    open() {
        return 'Welcome';
    }

    @http.GET('/admin').group('secret')
    secret() {
        return 'Welcome to the dark side';
    }
}

const app = new App({
    controllers: [MyWebsite],
    imports: [new FrameworkModule]
})

app.listen(httpWorkflow.onController, async (event) => {
    if (event.route.groups.includes('secret')) {
        //在此检查身份验证信息,例如 Cookie 会话、JWT 等。

        //这会跳转到 'accessDenied' 工作流状态,
        // 从而执行所有 onAccessDenied 监听器。

        //由于我们的监听器在 HTTP 内核监听器之前被调用,
        // 标准的控制器动作将不会被调用。
        // 底层等同于调用 event.next('accessDenied', ...)
        event.accessDenied();
    }
});

/**
 * 我们更改默认的 accessDenied 实现。
 */
app.listen(httpWorkflow.onAccessDenied, async () => {
    if (event.sent) return;
    if (event.hasNext()) return;
    event.send(new HtmlResponse('No access to this area.', 403));
})

app.run();
$ curl http://localhost:8080/
Welcome
$ curl http://localhost:8080/admin
No access to this area
English中文 (Chinese)한국어 (Korean)日本語 (Japanese)Deutsch (German)