view method
Renders an HTML template and writes it to the response.
This method:
- resolves the configured TemplateEngine
- loads the authenticated user into session state
- reuses or generates a CSRF token
- merges provided
datawith session and CSRF values - renders the template into HTML
- configures response headers and content length
- stores a CSRF cookie when a new token is generated
Parameters:
template: The template identifier to render.data: Optional view data passed into the template.
Returns the active HttpResponse after writing and closing it.
Example:
return request.view('users.show', {
'user': user,
'pageTitle': 'User Profile',
});
Implementation
Future<HttpResponse> view(String template, [ViewData? data]) async {
final container = App().container; // Cache reference
final engine = container.make<TemplateEngine>();
// 1. Parallelize data fetching if possible, but definitely cache user
thisSession?.user = await Auth.user(this);
// 2. Optimized Cookie Access: Search cookies ONCE
Cookie? csrfCookie;
Cookie? guestCookie;
for (var c in cookies) {
if (c.name == 'archery_csrf_token') csrfCookie = c;
if (c.name == 'archery_guest_session') guestCookie = c;
if (csrfCookie != null && guestCookie != null) break;
}
String token;
bool isNewToken = false;
if (data?.containsKey('csrf_token') ?? false) {
token = data!['csrf_token'];
} else if (csrfCookie != null) {
token = csrfCookie.value;
} else {
token = App.generateKey();
isNewToken = true;
}
try {
// 3. Merging data: Use a single map spread
final viewData = {
...?data,
"session": thisSession?.toJson(),
'csrf_token': token
};
final html = await engine.render(template, viewData);
final bodyBytes = utf8.encode(html);
// 4. Batch Header Setting
response.headers.contentLength = bodyBytes.length;
_viewHeaders.forEach(response.headers.set);
response.persistentConnection = true;
if (isNewToken) {
response.cookies.add(
Cookie('archery_csrf_token', token)
..httpOnly = true ..secure = true
..sameSite = SameSite.lax ..path = '/'
);
}
// 5. Direct lookup for sessions list
final sessions = App().tryMake<List<Session>>();
if (sessions != null && guestCookie != null) {
final session = sessions.firstWhereOrNull((s) => s.token == guestCookie!.value);
if (session != null) session.csrf = token;
}
return response
..add(bodyBytes) // Use .add() for bytes to bypass re-encoding strings
..close();
} catch (e) {
return response
..write("error") // Use .add() for bytes to bypass re-encoding strings
..close();
}
}