# Request data persistence

Express provide different way to persist data on request as following:

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

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

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

# Locals

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

If you don't want that don't use this attributes!

Here 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 return the created by Ts.ED when 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 contain all services annotated with @Scope(ProviderScope.REQUEST),
  • The current resolved by Ts.ED during the request,
  • The data return by the previous endpoint if you use multiple handler on the same route. By default data is empty.

Here an example:

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

@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 store all log and Ts.ED print (flush) all log after the response is send by the server. The approach optimize performance by sending in first the response and then print all logs.