Dart HttpOverrides
last modified October 18, 2026
The HttpOverrides class in Dart allows customization of HTTP
requests made through the dart:io HttpClient. It's useful for
testing, mocking, and modifying HTTP behavior.
HttpOverrides provides hooks to intercept and modify HTTP requests globally. This includes certificate validation and proxy configuration.
Basic Definition
HttpOverrides is an abstract class in Dart's dart:io
library. It serves as a global hook point for HTTP request customization.
Key methods include createHttpClient for client creation and
findProxyFromEnvironment for proxy configuration. These can be
overridden.
Basic HttpOverrides Usage
This example shows how to set up basic HttpOverrides for all HTTP requests.
import 'dart:io';
class MyHttpOverrides extends HttpOverrides {
@override
HttpClient createHttpClient(SecurityContext? context) {
return super.createHttpClient(context)
..userAgent = 'MyCustomAgent/1.0';
}
}
void main() async {
HttpOverrides.global = MyHttpOverrides();
final client = HttpClient();
final request = await client.getUrl(Uri.parse('https://example.com'));
final response = await request.close();
await response.drain<void>();
print('Request completed with status: ${response.statusCode}');
client.close();
}
We create a custom HttpOverrides class that sets a user agent for all requests. The global instance is set before making any HTTP requests.
$ dart main.dart Request completed with status: 200
Custom Certificate Validation
This example demonstrates overriding certificate validation for testing.
import 'dart:io';
class TrustAllHttpOverrides extends HttpOverrides {
@override
HttpClient createHttpClient(SecurityContext? context) {
return super.createHttpClient(context)
..badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
}
}
void main() async {
HttpOverrides.global = TrustAllHttpOverrides();
try {
final client = HttpClient();
final request = await client.getUrl(
Uri.parse('https://self-signed.badssl.com/'));
final response = await request.close();
await response.drain<void>();
print('Successfully connected to self-signed cert site');
client.close();
} catch (e) {
print('Error: $e');
}
}
We bypass certificate validation by always returning true in the callback. This is useful for testing but should never be used in production code.
$ dart main.dart Successfully connected to self-signed cert site
Proxy Configuration
This example shows how to configure a proxy for all HTTP requests.
import 'dart:convert';
import 'dart:io';
class ProxyHttpOverrides extends HttpOverrides {
@override
String findProxyFromEnvironment(Uri url, Map<String, String>? environment) {
return 'PROXY localhost:8080';
}
}
void main() async {
final proxy = await HttpServer.bind('localhost', 8080);
proxy.listen((request) async {
request.response
..headers.contentType = ContentType.text
..write('Response from proxy');
await request.response.close();
});
HttpOverrides.global = ProxyHttpOverrides();
final client = HttpClient();
final request = await client.getUrl(Uri.parse('http://example.com'));
final response = await request.close();
final body = await utf8.decoder.bind(response).join();
print('Request completed via proxy');
print(body);
client.close();
await proxy.close(force: true);
}
We override the proxy configuration to route all requests through a local proxy server. The findProxyFromEnvironment method returns the proxy string, and the test server answers the forwarded request.
$ dart main.dart Request completed via proxy Response from proxy
Request Header Modification
This example demonstrates adding custom headers to all requests.
import 'dart:io';
class CustomHeadersHttpOverrides extends HttpOverrides {
@override
HttpClient createHttpClient(SecurityContext? context) {
return _HeaderAddingClient(super.createHttpClient(context));
}
}
class _HeaderAddingClient implements HttpClient {
final HttpClient _inner;
_HeaderAddingClient(this._inner);
@override
Future<HttpClientRequest> getUrl(Uri url) async {
final request = await _inner.getUrl(url);
request.headers.add('X-Custom-Header', 'MyValue');
request.headers.add('Authorization', 'Bearer mytoken');
return request;
}
@override
void close({bool force = false}) => _inner.close(force: force);
@override
dynamic noSuchMethod(Invocation invocation) =>
super.noSuchMethod(invocation);
}
void main() async {
HttpOverrides.global = CustomHeadersHttpOverrides();
final client = HttpClient();
final request = await client.getUrl(Uri.parse('https://example.com'));
final response = await request.close();
await response.drain<void>();
print('Request with custom headers completed: ${response.statusCode}');
client.close();
}
HttpOverrides cannot modify request headers directly. We wrap the client
returned by createHttpClient and add headers in
getUrl, so every request created through the wrapper receives them.
$ dart main.dart Request with custom headers completed: 200
Mocking HTTP Responses
This example shows how to mock HTTP responses for testing purposes.
import 'dart:async';
import 'dart:convert';
import 'dart:io';
class MockHttpOverrides extends HttpOverrides {
@override
HttpClient createHttpClient(SecurityContext? context) {
return _MockHttpClient();
}
}
class _MockHttpClient implements HttpClient {
@override
Future<HttpClientRequest> getUrl(Uri url) async {
return _MockHttpClientRequest();
}
@override
void close({bool force = false}) {}
@override
dynamic noSuchMethod(Invocation invocation) =>
super.noSuchMethod(invocation);
}
class _MockHttpClientRequest implements HttpClientRequest {
@override
Future<HttpClientResponse> close() async {
return _MockHttpClientResponse();
}
@override
dynamic noSuchMethod(Invocation invocation) =>
super.noSuchMethod(invocation);
}
class _MockHttpClientResponse implements HttpClientResponse {
final Stream<List<int>> _body =
Stream.value(utf8.encode('{"message": "Mock response"}'));
@override
int get statusCode => HttpStatus.ok;
@override
bool get isBroadcast => _body.isBroadcast;
@override
StreamSubscription<List<int>> listen(
void Function(List<int> event)? onData, {
Function? onError,
void Function()? onDone,
bool? cancelOnError,
}) {
return _body.listen(
onData,
onError: onError,
onDone: onDone,
cancelOnError: cancelOnError,
);
}
@override
dynamic noSuchMethod(Invocation invocation) =>
super.noSuchMethod(invocation);
}
void main() async {
HttpOverrides.global = MockHttpOverrides();
final client = HttpClient();
final request = await client.getUrl(Uri.parse('https://example.com'));
final response = await request.close();
final data = await utf8.decoder.bind(response).join();
print('Mock response: $data');
client.close();
}
We implement a mock HTTP client that returns predefined responses. Only the
members used by this example are implemented; noSuchMethod handles
the rest of the HttpClient interfaces.
$ dart main.dart
Mock response: {"message": "Mock response"}
Best Practices
- Testing Only: Use certificate bypass only in test environments
- Performance: Keep overrides lightweight to avoid slowdowns
- Security: Never hardcode credentials in production code
- Cleanup: Reset HttpOverrides.global when done testing
Source
Dart HttpOverrides Documentation
This tutorial covered Dart's HttpOverrides class with practical examples showing request customization, proxy setup, and testing techniques.
Author
List all Dart tutorials.