Skip to main content
When rendering on the server, you can access request headers and cookies, and modify response headers, cookies, and status codes through the BuildContext extension.
These APIs are only available on the server. They will throw an error if called on the client.

Reading Request Data

headers

Access HTTP headers from the current request with case-insensitive keys.
Map<String, String> get headers
If a header occurs more than once, they are concatenated with a comma. Example:
Builder(
  builder: (context) {
    final userAgent = context.headers['user-agent'];
    final acceptLanguage = context.headers['accept-language'];
    
    return div([], [
      text('User Agent: $userAgent'),
      text('Language: $acceptLanguage'),
    ]);
  },
)

headersAll

Access HTTP headers with multiple values.
Map<String, List<String>> get headersAll
If a header occurs only once, its value is a singleton list. If a header occurs with no value, the empty string is used. Example:
Builder(
  builder: (context) {
    final acceptHeaders = context.headersAll['accept'];
    
    return div([], [
      text('Accept headers: ${acceptHeaders?.join(", ")}'),
    ]);
  },
)

cookies

Access cookies sent with the current request.
Map<String, String> get cookies
Example:
Builder(
  builder: (context) {
    final sessionId = context.cookies['session_id'];
    final theme = context.cookies['theme'] ?? 'light';
    
    return div([], [
      text('Session: $sessionId'),
      text('Theme: $theme'),
    ]);
  },
)

url

Access the URL of the current request.
String get url
Example:
Builder(
  builder: (context) {
    final currentUrl = context.url;
    
    return div([], [
      text('Current URL: $currentUrl'),
    ]);
  },
)

Modifying Response Data

setHeader()

Set a response header.
void setHeader(String name, String value)
name
String
required
The name of the header.
value
String
required
The value of the header.
Example:
Builder(
  builder: (context) {
    // Set custom headers
    context.setHeader('X-Custom-Header', 'MyValue');
    context.setHeader('Cache-Control', 'max-age=3600');
    
    return div([], [text('Headers set!')]);
  },
)

setCookie()

Set a cookie in the response.
void setCookie(
  String name,
  String value, {
  DateTime? expires,
  int? maxAge,
  String? domain,
  String? path,
  bool secure = false,
  bool httpOnly = true,
  SameSite? sameSite,
})
name
String
required
The name of the cookie. Must be composed of valid characters according to RFC 6265.
value
String
required
The value of the cookie. Must be composed of valid characters according to RFC 6265.
expires
DateTime
The time at which the cookie expires.
maxAge
int
The number of seconds until the cookie expires. A zero or negative value means the cookie has expired.
domain
String
The domain that the cookie applies to.
path
String
The path within the domain that the cookie applies to.
secure
bool
default:"false"
Whether to only send this cookie on secure (HTTPS) connections.
httpOnly
bool
default:"true"
Whether the cookie is only sent in HTTP requests and is not accessible to client-side scripts.
sameSite
SameSite
Controls whether the cookie is sent with cross-site requests. Values: SameSite.strict, SameSite.lax, or SameSite.none.
Example:
import 'dart:io'; // For SameSite

Builder(
  builder: (context) {
    // Set a simple cookie
    context.setCookie('theme', 'dark');
    
    // Set a cookie with options
    context.setCookie(
      'session_id',
      'abc123xyz',
      maxAge: 3600, // 1 hour
      path: '/',
      secure: true,
      httpOnly: true,
      sameSite: SameSite.strict,
    );
    
    // Set a cookie with expiration date
    context.setCookie(
      'remember_me',
      'true',
      expires: DateTime.now().add(Duration(days: 30)),
      path: '/',
    );
    
    return div([], [text('Cookies set!')]);
  },
)

setStatusCode()

Set the response status code.
void setStatusCode(int statusCode, {Object? responseBody})
statusCode
int
required
The HTTP status code (e.g., 200, 404, 500).
responseBody
String | Uint8List
Optional response body to send instead of the rendered HTML. Supported types are String and Uint8List.
Example:
Builder(
  builder: (context) {
    // Set a custom status code
    context.setStatusCode(201);
    
    return div([], [text('Created!')]);
  },
)

Custom Response Body

You can override the rendered HTML and send a custom response:
import 'dart:convert';

Builder(
  builder: (context) {
    // Check if this is an API request
    if (context.url.startsWith('/api/')) {
      // Return JSON instead of HTML
      context.setStatusCode(
        200,
        responseBody: jsonEncode({
          'status': 'ok',
          'data': {'message': 'Hello, API!'}
        }),
      );
      context.setHeader('Content-Type', 'application/json');
    }
    
    return div([], [text('Normal HTML response')]);
  },
)
Binary Response:
import 'dart:typed_data';

Builder(
  builder: (context) {
    if (context.url == '/image') {
      final imageBytes = Uint8List.fromList([/* ... */]);
      context.setStatusCode(200, responseBody: imageBytes);
      context.setHeader('Content-Type', 'image/png');
    }
    
    return div([], [text('Page')]);
  },
)

Complete Example

import 'dart:io';
import 'package:jaspr/jaspr.dart';

class AuthenticatedPage extends StatelessComponent {
  @override
  Component build(BuildContext context) {
    // Check for authentication cookie
    final authToken = context.cookies['auth_token'];
    
    if (authToken == null) {
      // No auth token - redirect to login
      context.setStatusCode(302);
      context.setHeader('Location', '/login');
      
      return div([], [text('Redirecting to login...')]);
    }
    
    // Validate token (simplified)
    if (!isValidToken(authToken)) {
      context.setStatusCode(401);
      
      return div([], [
        h1([], [text('Unauthorized')]),
        p([], [text('Your session has expired.')]),
      ]);
    }
    
    // Get user info from headers
    final userAgent = context.headers['user-agent'] ?? 'Unknown';
    final acceptLanguage = context.headers['accept-language'] ?? 'en';
    
    // Set custom response headers
    context.setHeader('X-Frame-Options', 'DENY');
    context.setHeader('X-Content-Type-Options', 'nosniff');
    
    // Refresh the auth cookie
    context.setCookie(
      'auth_token',
      authToken,
      maxAge: 3600,
      httpOnly: true,
      secure: true,
      sameSite: SameSite.strict,
    );
    
    return div([], [
      h1([], [text('Welcome!')]),
      p([], [text('Browser: $userAgent')]),
      p([], [text('Language: $acceptLanguage')]),
    ]);
  }
  
  bool isValidToken(String token) {
    // Token validation logic
    return token.isNotEmpty;
  }
}

Use Cases

Authentication & Authorization

final token = context.cookies['auth_token'];
if (token == null) {
  context.setStatusCode(401);
  return LoginPrompt();
}

Redirects

context.setStatusCode(302);
context.setHeader('Location', '/new-location');

Content Negotiation

final accept = context.headers['accept'];
if (accept?.contains('application/json') ?? false) {
  context.setStatusCode(200, responseBody: jsonEncode(data));
  context.setHeader('Content-Type', 'application/json');
}

Custom Caching

context.setHeader('Cache-Control', 'public, max-age=31536000');
context.setHeader('ETag', generateETag(content));

Session Management

context.setCookie(
  'session_id',
  generateSessionId(),
  maxAge: 3600,
  httpOnly: true,
  sameSite: SameSite.strict,
);
These APIs only work on the server. If you try to use them in a client-rendered component (e.g., inside a @client component), they will throw an error.

See Also

Build docs developers (and LLMs) love