ZetCode

Dart HttpOverrides

最后修改于 2025 年 4 月 4 日

Dart 中的 HttpOverrides 类允许自定义通过 dart:io HttpClient 发起的 HTTP 请求。它对于测试、模拟和修改 HTTP 行为非常有用。

HttpOverrides 提供了用于拦截和全局修改 HTTP 请求的钩子。这包括证书验证、代理配置和请求头。

基本定义

HttpOverrides 是 Dart dart:io 库中的一个抽象类。它作为 HTTP 请求自定义的全局钩子点。

关键方法包括用于客户端创建的 createHttpClient 和用于代理配置的 findProxy。这些方法可以被重写。

基本 HttpOverrides 用法

此示例展示了如何为所有 HTTP 请求设置基本的 HttpOverrides。

main.dart
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();
  
  print('Request completed with status: ${response.statusCode}');
  client.close();
}

我们创建了一个自定义的 HttpOverrides 类,为所有请求设置用户代理。全局实例在发起任何 HTTP 请求之前设置。

$ dart main.dart
Request completed with status: 200

自定义证书验证

此示例演示了重写用于测试的证书验证。

main.dart
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();
    print('Successfully connected to self-signed cert site');
    client.close();
  } catch (e) {
    print('Error: $e');
  }
}

我们通过在回调中始终返回 true 来绕过证书验证。这对于测试很有用,但绝不应在生产代码中使用。

$ dart main.dart
Successfully connected to self-signed cert site

代理配置

此示例展示了如何为所有 HTTP 请求配置代理。

main.dart
import 'dart:io';

class ProxyHttpOverrides extends HttpOverrides {
  @override
  String findProxyFromEnvironment(Uri url, Map<String, String>? environment) {
    return 'PROXY myproxy.example.com:8080';
  }
}

void main() async {
  HttpOverrides.global = ProxyHttpOverrides();
  
  final client = HttpClient();
  final request = await client.getUrl(Uri.parse('https://example.com'));
  final response = await request.close();
  
  print('Request completed via proxy');
  client.close();
}

我们重写了代理配置,将所有请求通过指定的代理服务器路由。findProxyFromEnvironment 方法返回代理字符串。

$ dart main.dart
Request completed via proxy

请求头修改

此示例演示了为所有请求添加自定义请求头。

main.dart
import 'dart:io';

class CustomHeadersHttpOverrides extends HttpOverrides {
  @override
  HttpClient createHttpClient(SecurityContext? context) {
    return super.createHttpClient(context)
      ..addCredentials = _addCredentials
      ..addRequestHeaders = _addHeaders;
  }

  void _addCredentials(Uri url, String scheme, String realm) {
    // Credential logic here
  }

  void _addHeaders(Uri url, HttpClientRequest request) {
    request.headers.add('X-Custom-Header', 'MyValue');
    request.headers.add('Authorization', 'Bearer mytoken');
  }
}

void main() async {
  HttpOverrides.global = CustomHeadersHttpOverrides();
  
  final client = HttpClient();
  final request = await client.getUrl(Uri.parse('https://example.com'));
  final response = await request.close();
  
  print('Request with custom headers completed');
  client.close();
}

我们为每个传出请求添加了静态和动态请求头。addRequestHeaders 回调在每个请求发送之前被调用。

$ dart main.dart
Request with custom headers completed

模拟 HTTP 响应

此示例展示了如何为测试目的模拟 HTTP 响应。

main.dart
import 'dart:io';
import 'dart:convert';

class MockHttpOverrides extends HttpOverrides {
  @override
  HttpClient createHttpClient(SecurityContext? context) {
    return _MockHttpClient();
  }
}

class _MockHttpClient implements HttpClient {
  @override
  Future<HttpClientRequest> getUrl(Uri url) async {
    return _MockHttpClientRequest();
  }
  
  // Other required overrides omitted for brevity
}

class _MockHttpClientRequest implements HttpClientRequest {
  @override
  Future<HttpClientResponse> close() async {
    return _MockHttpClientResponse();
  }
  
  // Other required overrides omitted for brevity
}

class _MockHttpClientResponse implements HttpClientResponse {
  @override
  int get statusCode => 200;
  
  @override
  Stream<Uint8List> get body => 
      Stream.value(utf8.encode('{"message": "Mock response"}'));
  
  // Other required overrides omitted for brevity
}

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 response.transform(utf8.decoder).join();
  print('Mock response: $data');
  client.close();
}

我们实现了一个完整的模拟 HTTP 客户端,该客户端返回预定义的响应。这对于在不进行实际网络请求的情况下进行测试很有用。

$ dart main.dart
Mock response: {"message": "Mock response"}

最佳实践

来源

Dart HttpOverrides 文档

本教程介绍了 Dart 的 HttpOverrides 类,并通过实际示例展示了请求自定义、代理设置和测试技术。

作者

我叫 Jan Bodnar,是一名充满热情的程序员,拥有丰富的编程经验。我自 2007 年以来一直在撰写编程文章。迄今为止,我已撰写了 1,400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出 所有 Dart 教程