Dart HttpHeaders
last modified October 18, 2026
The HttpHeaders class in Dart provides functionality to manage
HTTP headers for requests and responses. It's part of Dart's
dart:io library.
HttpHeaders handles header name case sensitivity, multiple values, and special headers like content-length automatically. It's used with HttpClient and HttpServer classes.
Basic Definition
HttpHeaders is an abstract class representing HTTP headers.
It provides methods to add, set, remove, and inspect headers.
Key features include case-insensitive header names, value list management, and special handling for cookies and content headers. It's immutable once frozen.
Creating HttpHeaders
This example shows how to obtain a mutable HttpHeaders object from an HTTP response and populate it.
import 'dart:io';
Future<void> _withHeaders(void Function(HttpHeaders) action) async {
var server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
var client = HttpClient();
try {
var url = Uri.parse('http://${server.address.address}:${server.port}/');
var request = await client.getUrl(url);
var responseFuture = request.close();
var httpRequest = await server.first;
action(httpRequest.response.headers);
await httpRequest.response.close();
await (await responseFuture).drain<void>();
} finally {
client.close(force: true);
await server.close(force: true);
}
}
Future<void> main() async {
await _withHeaders((headers) {
headers.add('Content-Type', 'text/html');
headers.add('X-Custom-Header', 'value1');
headers.add('X-Custom-Header', 'value2');
print('Content-Type: ${headers.value('content-type')}');
print('X-Custom-Header: ${headers['x-custom-header']}');
});
}
HttpHeaders cannot be constructed directly, so we obtain it from a server response. Header names are case-insensitive. The same header can have multiple values. Values can be accessed by name.
$ dart main.dart Content-Type: text/html X-Custom-Header: [value1, value2]
Setting vs Adding Headers
This example demonstrates the difference between set and add operations.
import 'dart:io';
Future<void> _withHeaders(void Function(HttpHeaders) action) async {
var server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
var client = HttpClient();
try {
var url = Uri.parse('http://${server.address.address}:${server.port}/');
var request = await client.getUrl(url);
var responseFuture = request.close();
var httpRequest = await server.first;
action(httpRequest.response.headers);
await httpRequest.response.close();
await (await responseFuture).drain<void>();
} finally {
client.close(force: true);
await server.close(force: true);
}
}
Future<void> main() async {
await _withHeaders((headers) {
headers.add('Accept', 'text/html');
headers.add('Accept', 'application/json');
print('Before set: ${headers['accept']}');
headers.set('Accept', 'image/png');
print('After set: ${headers['accept']}');
headers.remove('accept', 'image/png');
print('After remove: ${headers['accept']}');
});
}
Add appends values while set replaces all existing values. Remove deletes specific values. All operations are case-insensitive.
$ dart main.dart Before set: [text/html, application/json] After set: [image/png] After remove: null
Content Headers
This example shows special handling for content-related headers.
import 'dart:io';
Future<void> _withHeaders(void Function(HttpHeaders) action) async {
var server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
var client = HttpClient();
try {
var url = Uri.parse('http://${server.address.address}:${server.port}/');
var request = await client.getUrl(url);
var responseFuture = request.close();
var httpRequest = await server.first;
action(httpRequest.response.headers);
await httpRequest.response.close();
await (await responseFuture).drain<void>();
} finally {
client.close(force: true);
await server.close(force: true);
}
}
Future<void> main() async {
await _withHeaders((headers) {
headers.contentType = ContentType('text', 'html', charset: 'utf-8');
headers.contentLength = 0;
headers.chunkedTransferEncoding = false;
print('Content-Type: ${headers.contentType}');
print('Content-Length: ${headers.contentLength}');
print('Chunked: ${headers.chunkedTransferEncoding}');
});
}
Content headers have dedicated properties for type, length, and encoding. These properties provide type-safe access to common HTTP content headers. The response uses a zero-length body, so Content-Length is set to 0.
$ dart main.dart Content-Type: text/html; charset=utf-8 Content-Length: 0 Chunked: false
Date and Cookie Headers
This example demonstrates date and cookie header handling.
import 'dart:io';
Future<void> _withHeaders(void Function(HttpHeaders) action) async {
var server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
var client = HttpClient();
try {
var url = Uri.parse('http://${server.address.address}:${server.port}/');
var request = await client.getUrl(url);
var responseFuture = request.close();
var httpRequest = await server.first;
action(httpRequest.response.headers);
await httpRequest.response.close();
await (await responseFuture).drain<void>();
} finally {
client.close(force: true);
await server.close(force: true);
}
}
Future<void> main() async {
await _withHeaders((headers) {
var date = DateTime.utc(2025, 4, 4, 12, 34, 56);
headers.date = date;
headers.add('Set-Cookie',
'id=a3fWa; Expires=Wed, 21 Oct 2025 07:28:00 GMT');
headers.add('Set-Cookie', 'session=abc123; HttpOnly');
print('Date: ${headers.date}');
print('Cookies:');
headers.forEach((name, values) {
if (name == 'set-cookie') {
values.forEach(print);
}
});
});
}
Date headers are handled with DateTime objects. Cookies can be added as strings but are specially formatted. The forEach method iterates through all headers.
$ dart main.dart Date: 2025-04-04 12:34:56.000Z Cookies: id=a3fWa; Expires=Wed, 21 Oct 2025 07:28:00 GMT session=abc123; HttpOnly
HttpClient with Headers
This example shows using HttpHeaders with HttpClient requests.
import 'dart:convert';
import 'dart:io';
Future<void> main() async {
var server = await HttpServer.bind(InternetAddress.loopbackIPv4, 0);
server.listen((request) async {
var accept = request.headers.value('accept');
var userAgent = request.headers.value('user-agent');
var requestId = request.headers.value('x-request-id');
request.response.write('$accept|$userAgent|$requestId');
await request.response.close();
});
var client = HttpClient();
try {
var url = Uri.parse('http://${server.address.address}:${server.port}/');
var request = await client.getUrl(url);
request.headers.add('Accept', 'application/json');
request.headers.set('User-Agent', 'Dart/3.0');
request.headers.add('X-Request-ID', '12345');
var response = await request.close();
print('Status: ${response.statusCode}');
var body = await response.transform(utf8.decoder).join();
print('Response length: ${body.length}');
} finally {
client.close(force: true);
await server.close(force: true);
}
}
We create an HTTP GET request with custom headers and send it to a local server. The headers property is an HttpHeaders instance; the server reads the values and echoes them back in the response body.
$ dart main.dart Status: 200 Response length: 31
Best Practices
- Reuse clients: Reuse an HttpClient for multiple requests
- Validation: Validate header values before setting
- Constants: Use constants for header names
- Security: Sanitize user-provided header values
Source
Dart HttpHeaders Documentation
This tutorial covered Dart's HttpHeaders class with practical examples showing header management, special headers, and HTTP client integration.
Author
List all Dart tutorials.