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. For example, what if the res.session was storing the id of the current user. 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.
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.
For such tasks vibe.d provides TaskLocal template which allows to do exactly what you want. I have not tried it but expect
TaskLocal!Session session
to "just work".Please pay attention to these two warnings from docs:
and
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.