简体   繁体   English

是否可以在vibe.d中全局存储当前会话信息? (dlang)

[英]Is it possible to store current session information globally in vibe.d? (dlang)

The example from the site: 该站点的示例:

import vibe.d;

void login(HTTPServerRequest req, HTTPServerResponse res)
{
    enforceHTTP("username" in req.form && "password" in req.form,
        HTTPStatus.badRequest, "Missing username/password field.");

    // todo: verify user/password here

    auto session = res.startSession();
    session["username"] = req.form["username"];
    session["password"] = req.form["password"];
    res.redirect("/home");
}

void logout(HTTPServerRequest req, HTTPServerResponse res)
{
    res.terminateSession();
    res.redirect("/");
}

void checkLogin(HTTPServerRequest req, HTTPServerResponse res)
{
    // force a redirect to / for unauthenticated users
    if( req.session is null )
        res.redirect("/");
}

shared static this()
{
    auto router = new URLRouter;
    router.get("/", staticTemplate!"index.dl");
    router.post("/login", &login);
    router.post("/logout", &logout);
    // restrict all following routes to authenticated users:
    router.any("*", &checkLogin);
    router.get("/home", staticTemplate!"home.dl");

    auto settings = new HTTPServerSettings;
    settings.sessionStore = new MemorySessionStore;
    // ...
}

But lets say I didnt want to pass the ServerResponse throughout my program into every function. 但是可以说我不想在整个程序中将ServerResponse传递给每个函数。 For example, what if the res.session was storing the id of the current user. 例如,如果res.session正在存储当前用户的ID,该怎么办。 This is used often, so I wouldnt want this passed through each function. 这是经常使用的,所以我不希望这通过每个函数传递。 How do I store this session info globally? 如何在全球范围内存储此会话信息? Assuming there's multiple users using the site. 假设有多个用户正在使用该网站。

It is possible, though kind of discouraged. 这是可能的,尽管有些气disc。

Solution

You can't simply store it globally because there is not such thing as "global" session - it is always specific to request context. 您不能简单地将其全局存储,因为没有“全局”会话之类的东西-它始终特定于请求上下文。 Even having globals thread-local by default in D does not help as multiple fibers share same execution thread. 即使默认情况下在D中具有全局线程局部变量也无济于事,因为多个光纤共享同一执行线程。

For such tasks vibe.d provides TaskLocal template which allows to do exactly what you want. 对于此类任务,vibe.d提供了TaskLocal模板,该模板可完全执行您想要的操作。 I have not tried it but expect TaskLocal!Session session to "just work". 我还没有尝试过,但是希望TaskLocal!Session session能够“正常工作”。

Please pay attention to these two warnings from docs: 请注意文档中的以下两个警告:

Note, however, that each TaskLocal variable will increase the memory footprint of any task that uses task local storage. 但是请注意,每个TaskLocal变量都会增加使用任务本地存储的任何任务的内存占用。 There is also an overhead to access TaskLocal variables, higher than for thread local variables, but generally still O(1) 访问TaskLocal变量的开销也比线程局部变量的开销高,但是通常仍然为O(1)

and

FiberLocal instances MUST be declared as static/global thread-local variables. 必须将FiberLocal实例声明为静态/全局线程局部变量。 Defining them as a temporary/stack variable will cause crashes or data corruption! 将它们定义为临时/堆栈变量将导致崩溃或数据损坏!

Objection 异议

Based on my experience, however, it still better to pass all such context explicitly through despite small typing inconvenience. 但是,根据我的经验,尽管打字带来一些不便,但最好还是将所有此类上下文显式传递出去。 Using globals is discouraged for a reason - as your program size grows it becomes inevitably hard to track dependencies between modules and test such code. 出于某种原因,不建议使用全局变量-随着程序大小的增加,不可避免地将很难跟踪模块之间的依赖关系并测试此类代码。 Falling to convenience temptation now may cause lot of headache later. 现在陷入便利诱惑可能会在以后引起很多头痛。 To minimize extra typing and simplify code maintenance I may suggest to instead define struct Context { ...} which will contain request / session pointers and will be routinely passed around instead. 为了最大程度地减少额外的输入并简化代码维护,我可能建议改为定义struct Context { ...} ,该struct Context { ...}将包含请求/会话指针,并且将按常规传递。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM