view method

Future<HttpResponse> view(
  1. String template, [
  2. ViewData? data
])

Renders a template and sends HTML response.

  • Sets Content-Type: text/html
  • Adds caching and security headers
  • Sets XSRF token cookie
  • Handles errors gracefully in debug mode

Implementation

Future<HttpResponse> view(String template, [ViewData? data]) async {
  final engine = App().container.make<TemplateEngine>();
  final config = App().container.make<AppConfig>();

  final user = await Auth.user(this);
  if (user != null) {
    final userData = {"user": user.toJson()};
    data = {...?data, ...userData};
  }

  try {
    final html = engine.render(template, data ?? {});

    // --- Performance headers ---
    response.headers.contentType = ContentType.html;
    response.headers.set(HttpHeaders.varyHeader, 'Accept-Encoding');

    response.headers.set(
      HttpHeaders.cacheControlHeader,
      'no-cache, no-store, must-revalidate, max-age=0',
    );
    response.headers.set(
      HttpHeaders.pragmaHeader,
      'no-cache',
    ); // HTTP/1.0 compatibility
    response.headers.set(
      HttpHeaders.expiresHeader,
      '0',
    ); // or a date in the past, e.g., 'Tue, 01 Jan 1980 00:00:00 GMT'
    //
    // // --- Security headers ---
    response.headers.set('X-Content-Type-Options', 'nosniff');
    response.headers.set('X-Frame-Options', 'SAMEORIGIN');
    response.headers.set(
      'Referrer-Policy',
      'strict-origin-when-cross-origin',
    );
    response.headers.set('X-XSS-Protection', '1; mode=block');

    final cookie = Cookie('archery_csrf_token', App.generateKey())
      ..httpOnly = true
      ..secure = true
      ..sameSite = SameSite.lax;

    final sessions = App().tryMake<List<Session>>();
    if (sessions != null && sessions.isNotEmpty) {
      final requestCookie = cookies.firstWhereOrNull(
        (cookie) => cookie.name == "archery_guest_session",
      );

      if (requestCookie != null) {
        final session = sessions.firstWhereOrNull(
          (session) => session.token == requestCookie.value,
        );

        if (session != null) {
          session.csrf = cookie.value;
        }
      }
    }

    return response
      ..cookies.add(cookie)
      ..write(html)
      ..close();
  } catch (e, stack) {
    if (config.get('app.debug')) {
      return response
        ..statusCode = HttpStatus.internalServerError
        ..write("$e\n\n$stack")
        ..close();
    }
    return response
      ..statusCode = HttpStatus.internalServerError
      ..write(e)
      ..close();
  }
}