Override http package globally in Flutter

Viewed 1714

I am trying to override the http package globally in order to intercept requests from this package which uses the http package under the hood. While the constructor is called, none of the overridden methods are. I have added print statements for GET and POST requests. This is my override code:

void main() {
  HttpOverrides.global = MyHttpOverrides();
  runApp(...);
}
class MyHttpOverrides extends HttpOverrides {
  @override
  HttpClient createHttpClient(SecurityContext context) {
    var client = MyHttpClient(super.createHttpClient(context));
    return client;
  }
}
class MyHttpClient implements HttpClient {
  HttpClient _realClient;

  MyHttpClient(this._realClient) {
    print("initialized");
  }

  @override
  bool get autoUncompress => _realClient.autoUncompress;

  @override
  set autoUncompress(bool value) => _realClient.autoUncompress = value;

  @override
  Duration get connectionTimeout => _realClient.connectionTimeout;

  @override
  set connectionTimeout(Duration value) =>
      _realClient.connectionTimeout = value;

  @override
  Duration get idleTimeout => _realClient.idleTimeout;

  @override
  set idleTimeout(Duration value) => _realClient.idleTimeout = value;

  @override
  int get maxConnectionsPerHost => _realClient.maxConnectionsPerHost;

  @override
  set maxConnectionsPerHost(int value) =>
      _realClient.maxConnectionsPerHost = value;

  @override
  String get userAgent => _realClient.userAgent;

  @override
  set userAgent(String value) => _realClient.userAgent = value;

  @override
  void addCredentials(
          Uri url, String realm, HttpClientCredentials credentials) =>
      _realClient.addCredentials(url, realm, credentials);

  @override
  void addProxyCredentials(String host, int port, String realm,
          HttpClientCredentials credentials) =>
      _realClient.addProxyCredentials(host, port, realm, credentials);

  @override
  void set authenticate(
          Future<bool> Function(Uri url, String scheme, String realm) f) =>
      _realClient.authenticate = f;

  @override
  void set authenticateProxy(
          Future<bool> Function(
                  String host, int port, String scheme, String realm)
              f) =>
      _realClient.authenticateProxy = f;

  @override
  void set badCertificateCallback(
          bool Function(X509Certificate cert, String host, int port)
              callback) =>
      _realClient.badCertificateCallback = callback;

  @override
  void close({bool force = false}) => _realClient.close(force: force);

  @override
  Future<HttpClientRequest> delete(String host, int port, String path) =>
      _realClient.delete(host, port, path);

  @override
  Future<HttpClientRequest> deleteUrl(Uri url) => _realClient.deleteUrl(url);

  @override
  void set findProxy(String Function(Uri url) f) => _realClient.findProxy = f;

  @override
  Future<HttpClientRequest> get(String host, int port, String path) {
    print("get called");
    return _updateHeaders(_realClient.get(host, port, path));
  }

  Future<HttpClientRequest> _updateHeaders(
      Future<HttpClientRequest> httpClientRequest) async {
    return (await httpClientRequest)..headers.add('foo', 'bar');
  }

  @override
  Future<HttpClientRequest> getUrl(Uri url) =>
      _updateHeaders(_realClient.getUrl(url.replace(path: url.path)));

  @override
  Future<HttpClientRequest> head(String host, int port, String path) =>
      _realClient.head(host, port, path);

  @override
  Future<HttpClientRequest> headUrl(Uri url) => _realClient.headUrl(url);

  @override
  Future<HttpClientRequest> open(
          String method, String host, int port, String path) =>
      _realClient.open(method, host, port, path);

  @override
  Future<HttpClientRequest> openUrl(String method, Uri url) =>
      _realClient.openUrl(method, url);

  @override
  Future<HttpClientRequest> patch(String host, int port, String path) =>
      _realClient.patch(host, port, path);

  @override
  Future<HttpClientRequest> patchUrl(Uri url) => _realClient.patchUrl(url);

  @override
  Future<HttpClientRequest> post(String host, int port, String path) {
    print("post called");
    return _realClient.post(host, port, path);
  }

  @override
  Future<HttpClientRequest> postUrl(Uri url) {
    print("postUrl called");
    return _realClient.postUrl(url);
  }

  @override
  Future<HttpClientRequest> put(String host, int port, String path) =>
      _realClient.put(host, port, path);

  @override
  Future<HttpClientRequest> putUrl(Uri url) => _realClient.putUrl(url);
}

And this is the code that fires the POST request:

http.post(
      requestData.uri,
      headers: requestData.headers,
      body: requestData.body,
    );

I also tried making a POST request without the http package and in that case the overridden methods are called as expected.

    String _host = InternetAddress.loopbackIPv4.host;
    String path = 'file.txt';

    Map jsonData = {
      'name': 'Han Solo',
      'job': 'reluctant hero',
      'BFF': 'Chewbacca',
      'ship': 'Millennium Falcon',
      'weakness': 'smuggling debts'
    };

    HttpClientRequest request = await HttpClient().post(_host, 4049, path) /*1*/
      ..headers.contentType = ContentType.json /*2*/
      ..write(jsonEncode(jsonData)); /*3*/
    HttpClientResponse response = await request.close(); /*4*/
    await utf8.decoder.bind(response /*5*/).forEach(print);

Is there something special about the http package that I need to do?

1 Answers

HttpOverrides.global initializes MyHttpOverrides() as expected, but the plugin that you're using doesn't use the custom HttpOverrides you've created. The http package used in the plugin can't be overridden. You need to run the HTTP Requests using the http package by yourself to use the custom HttpClient that you've set up.

Related