# Request data persistence

Express provides different ways to persist data on request as following:

  • Directly on the request,
  • On response.locals,
  • On request.session and request.cookies

Ts.ED provides also a way to store and share data along all middlewares/endpoints during a request with .

Each approach is a valid way to persist data, but it's important to understand the difference between locals provided by express and context provided by Ts.ED.

# Locals

is a request property used by third-party like template engine to render a page by the server. If you attach data on it, you'll expose this data to the template.

If you don't want that, don't use this attribute!

Here is an example:

import {Controller, Get, Locals, Middleware, Render, UseBefore} from "@tsed/common";

@Middleware()
class LocalsMiddleware {
  use(@Locals() locals: any) {
    // set some on locals
    locals.user = "user";
  }
}

@Controller("/")
@UseBefore(LocalsMiddleware)
class MyCtrl {
  @Get("/")
  @Render("home.ejs") // will use locals and returned data to render the page
  get(@Locals("user") user: any) {
    console.log("user", user);

    return {
      description: "Hello world"
    };
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# Context

v5.34.2+

decorator will give you a way to store any data and retrieve to another middleware or endpoint without exposing it in the template.

Context decorator returns the created by Ts.ED when the request is handled by the server.

It contains some information as following:

  • The request id,
  • The request container used by the Ts.ED DI. It contains all services annotated with @Scope(ProviderScope.REQUEST),
  • The current resolved by Ts.ED during the request,
  • The data returned by the previous endpoint if you use multiple handlers on the same route. By default data is empty.

Here is an example:

import {Context, Controller, Get, Middleware, Req, UseBefore} from "@tsed/common";
import {Forbidden} from "@tsed/exceptions";

@Middleware()
class AuthTokenMiddleware {
  use(@Req() request: Express.Request, @Context() context: Context) {
    if (!context.has("auth")) {
      context.set("auth", new AuthToken(request));
    }

    try {
      context.get("auth").claims(); // check token
    } catch (er) {
      throw new Forbidden("Access forbidden - Bad token");
    }
  }
}

@Controller("/")
@UseBefore(AuthTokenMiddleware) // protect all routes for this controller
class MyCtrl {
  @Get("/")
  get(@Context() context: Context, @Context("auth") auth: AuthToken) {
    context.logger.info({event: "auth", auth}); // Attach log to the request
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

TIP

is attached to the context context.logger. The RequestLogger stores all logs and Ts.ED prints (flushes) all logs after the response is sent by the server. The approach optimizes performance by first sending in the response and then printing all logs.