Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Override HttpClient globally #19588

Closed
pepie opened this issue Jul 20, 2018 · 24 comments
Closed

Override HttpClient globally #19588

pepie opened this issue Jul 20, 2018 · 24 comments
Labels
dependency: dart Dart team may need to help us framework flutter/packages/flutter repository. See also f: labels.

Comments

@pepie
Copy link

pepie commented Jul 20, 2018

Hello,
I'm having trouble making network calls to a development box w/ a self-signed certificate.

Is there a way to override HttpClient globally?

Flutter throws a CERTIFICATE_VERIFY_FAILED, when making calls to a server with self-signed certificate.

This can be bypassed with the badCertificateCallback() like so

new HttpClient(context)
..._client.badCertificateCallback = (X509Certificate cert, String host, int port)=>true;

This must be done on a case-by-case basis, however, as overriding one client instance does not make it possible to use other features that depends on HttpClient, but does not expose the HttpClient object.

For example,
Suppose I want to

  1. call an api endpoint that returns an image url, and then
  2. load that image using NetworkImage()

The call to NetworkImage() would fail, because NetworkImage uses a new instance HttpClient:

HttpClient _client = new HttpClient(context:c);
_client.badCertificateCallback = (X509Certificate cert, String host, int port)=>true;
var response  = await _client.getUrl('https://localhost:443',...) .  //this will succeed
var imagePath = response.data.imagePath
...

//If I later try to load the image with
//we get a CERTIFICATE_VERIFY_FAILED exception
new NetworkImage(
'https://localhost:443/<image path value>.jpg',
...
) 

Is there a better way to do this?

@jonahwilliams
Copy link
Member

You can override all HTTP clients globally using HttpOverrides

For example:

class MyHttpOverrides extends HttpOverrides {
  @override
  HttpClient createHttpClient(SecurityContext securityContext) {
    return new HttpClient()
      .. badCertificateCallback = ...;
  }

void main() {
  HttpOverrides.global = new MyHttpOverrides();
  runApp(...)
}

We do this in flutter test as well with some mocks:

HttpOverrides.global = new _MockHttpOverrides();

@zoechi
Copy link
Contributor

zoechi commented Jul 20, 2018

Dup of #13792 ?

@pepie
Copy link
Author

pepie commented Jul 20, 2018

@jonahwilliams thanks!
I am getting a stack overflow with the following code:

class MyHttpOverrides extends HttpOverrides{
  @override
  HttpClient createHttpClient(SecurityContext securityContext){
    return new HttpClient(context: securityContext)
        ..badCertificateCallback =
            (X509Certificate cert, String host, int port) => true;
  }
}
void main() {
  HttpOverrides.global = new MyHttpOverrides();
  runApp(new MyApp());
}

//the call is

Future<String> getContent() async{
    var response = await http.get('https://jsonplaceholder.typicode.com/posts/1');
    return response.body;
  }```

@jonahwilliams
Copy link
Member

@pepie can you post the full stack trace?

@pepie
Copy link
Author

pepie commented Jul 20, 2018

@jonahwilliams Thanks for your help with this. I really appreciate it.

Here's the sample code:
[The code has been combined for simplicity]

I can see that createHttpClient() is called many times, which is likely what is overflowing the stack.
This the code referred as lib/main.dart:10:16, in the logs below.

import 'dart:async';
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:flutter/material.dart';
//import 'package:secure/utils/ApiHelper.dart';

class AppHttpOverrides extends HttpOverrides{
  @override
  HttpClient createHttpClient(SecurityContext securityContext){
    return new HttpClient()
    ..badCertificateCallback =(X509Certificate cert, String host, int port) => true;


  }
}

Future<String> getContent() async{
  var url = 'https://jsonplaceholder.typicode.com/posts/1';
  try{
    var response = await http.get(url);
    return response.body;
  }catch(err, stacktrace){
    print(err);
    debugPrint(stacktrace.toString());
    return err.toString();
  }
}

void main() {
  HttpOverrides.global = new AppHttpOverrides();
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      theme: new ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: new MyHomePage(title: 'HTTP DEMO'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}


class _MyHomePageState extends State<MyHomePage> {

  var _data = '[nothing yet]';

  void loadData() async{
    getContent().then((result){
      setState(() {
        _data = result;
      });
    }).catchError((err){
      _data = err.toString();
    }).whenComplete((){
      print('done!');
    });
  }

  @override
  Widget build(BuildContext context) {

    //ApiHelper rest = new ApiHelper();

    return new Scaffold(
      appBar: new AppBar(
        title: new Text(widget.title),
      ),
      body: Center(
        child: new Column(
            children: <Widget>[
              new Text('Web Result:',
                style: Theme.of(context).textTheme.display1,
              ),FutureBuilder(
                  future: getContent(),
                  //future: rest.getContent(),
                  builder: (context, snapshot){
                    if(snapshot.hasData){
                       return new Text(snapshot.data.toString());
                    }else if(snapshot.hasError){
                      print(snapshot.error.toString());
                      return new Text(snapshot.error.toString());
                    }

                    return new Container();
                  },
              ),
            ],
        ),
      ),
      floatingActionButton: new FloatingActionButton(
        onPressed: () {
          loadData();
        },
        tooltip: 'Load Data',
        child: new Icon(Icons.refresh),
      ),
    );
  }
}

Logs:

Performing hot reload...
Syncing files to device iPhone X...
flutter: Stack Overflow
flutter: #0      new HttpClient (dart:_http:1589:3)
flutter: #1      MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #2      new HttpClient (dart:_http:1594:22)
flutter: #3      MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #4      new HttpClient (dart:_http:1594:22)
flutter: #5      MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #6      new HttpClient (dart:_http:1594:22)
flutter: #7      MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #8      new HttpClient (dart:_http:1594:22)
flutter: #9      MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #10     new HttpClient (dart:_http:1594:22)
flutter: #11     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #12     new HttpClient (dart:_http:1594:22)
flutter: #13     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #14     new HttpClient (dart:_http:1594:22)
flutter: #15     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #16     new HttpClient (dart:_http:1594:22)
flutter: #17     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #18     new HttpClient (dart:_http:1594:22)
flutter: #19     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #20     new HttpClient (dart:_http:1594:22)
flutter: #21     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #22     new HttpClient (dart:_http:1594:22)
flutter: #23     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #24     new HttpClient (dart:_http:1594:22)
flutter: #25     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #26     new HttpClient (dart:_http:1594:22)
flutter: #27     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #28     new HttpClient (dart:_http:1594:22)
flutter: #29     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #30     new HttpClient (dart:_http:1594:22)
flutter: #31     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #32     new HttpClient (dart:_http:1594:22)
flutter: #33     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #34     new HttpClient (dart:_http:1594:22)
flutter: #35     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #36     new HttpClient (dart:_http:1594:22)
flutter: #37     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #38     new HttpClient (dart:_http:1594:22)
flutter: #39     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #40     new HttpClient (dart:_http:1594:22)
flutter: #41     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #42     new HttpClient (dart:_http:1594:22)
flutter: #43     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: ...
flutter: ...
flutter: #5944   Element.updateChild (package:flutter/src/widgets/framework.dart:2712:15)
flutter: #5945   ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3666:16)
flutter: #5946   Element.rebuild (package:flutter/src/widgets/framework.dart:3508:5)
flutter: #5947   StatefulElement.update (package:flutter/src/widgets/framework.dart:3812:5)
flutter: #5948   Element.updateChild (package:flutter/src/widgets/framework.dart:2712:15)
flutter: #5949   SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4674:14)
flutter: #5950   Element.updateChild (package:flutter/src/widgets/framework.dart:2712:15)
flutter: #5951   ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3666:16)
flutter: #5952   Element.rebuild (package:flutter/src/widgets/framework.dart:3508:5)
flutter: #5953   ProxyElement.update (package:flutter/src/widgets/framework.dart:3922:5)
flutter: #5954   Element.updateChild (package:flutter/src/widgets/framework.dart:2712:15)
flutter: #5955   SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4674:14)
flutter: #5956   Element.updateChild (package:flutter/src/widgets/framework.dart:2712:15)
flutter: #5957   ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3666:16)
flutter: #5958   Element.rebuild (package:flutter/src/widgets/framework.dart:3508:5)
flutter: #5959   StatefulElement.update (package:flutter/src/widgets/framework.dart:3812:5)
flutter: #5960   Element.updateChild (package:flutter/src/widgets/framework.dart:2712:15)
flutter: #5961   ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3666:16)
flutter: #5962   Element.rebuild (package:flutter/src/widgets/framework.dart:3508:5)
flutter: #5963   StatelessElement.update (package:flutter/src/widgets/framework.dart:3715:5)
flutter: #5964   Element.updateChild (package:flutter/src/widgets/framework.dart:2712:15)
flutter: #5965   SingleChildRenderObjectElement.update (package:flutter/src/widgets/framework.dart:4674:14)
flutter: #5966   Element.updateChild (package:flutter/src/widgets/framework.dart:2712:15)
flutter: #5967   ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3666:16)
flutter: #5968   Element.rebuild (package:flutter/src/widgets/framework.dart:3508:5)
flutter: #5969   ProxyElement.update (package:flutter/src/widgets/framework.dart:3922:5)
flutter: #5970   Element.updateChild (package:flutter/src/widgets/framework.dart:2712:15)
flutter: #5971   ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3666:16)
flutter: #5972   Element.rebuild (package:flutter/src/widgets/framework.dart:3508:5)
flutter: #5973   BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2255:33)
flutter: #5974   _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:626:20)
flutter: #5975   _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:208:5)
flutter: #5976   _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15)
flutter: #5977   _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930:9)
flutter: #5978   _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.scheduleWarmUpFrame.<anonymous closure> (package:flutter/src/scheduler/binding.dart:751:7)
flutter: #5979   Timer._createTimer.<anonymous closure> (dart:async/runtime/libtimer_patch.dart:21:15)
flutter: #5980   _Timer._runTimers (dart:isolate/runtime/libtimer_impl.dart:382:19)
flutter: #5981   _Timer._handleMessage (dart:isolate/runtime/libtimer_impl.dart:416:5)
flutter: #5982   _RawReceivePortImpl._handleMessage (dart:isolate/runtime/libisolate_patch.dart:165:12)
flutter:
Reloaded 1 of 499 libraries in 608ms.
flutter: Stack Overflow
flutter: #0      new HttpClient (dart:_http:1589:3)
flutter: #1      MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #2      new HttpClient (dart:_http:1594:22)
flutter: #3      MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #4      new HttpClient (dart:_http:1594:22)
flutter: #5      MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #6      new HttpClient (dart:_http:1594:22)
flutter: #7      MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #8      new HttpClient (dart:_http:1594:22)
flutter: #9      MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #10     new HttpClient (dart:_http:1594:22)
flutter: #11     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #12     new HttpClient (dart:_http:1594:22)
flutter: #13     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #14     new HttpClient (dart:_http:1594:22)
flutter: #15     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #16     new HttpClient (dart:_http:1594:22)
flutter: #17     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #18     new HttpClient (dart:_http:1594:22)
flutter: #19     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #20     new HttpClient (dart:_http:1594:22)
flutter: #21     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #22     new HttpClient (dart:_http:1594:22)
flutter: #23     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #24     new HttpClient (dart:_http:1594:22)
flutter: #25     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #26     new HttpClient (dart:_http:1594:22)
flutter: #27     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #28     new HttpClient (dart:_http:1594:22)
flutter: #29     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #30     new HttpClient (dart:_http:1594:22)
flutter: #31     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #32     new HttpClient (dart:_http:1594:22)
flutter: #33     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #34     new HttpClient (dart:_http:1594:22)
flutter: #35     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #36     new HttpClient (dart:_http:1594:22)
flutter: #37     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #38     new HttpClient (dart:_http:1594:22)
flutter: #39     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #40     new HttpClient (dart:_http:1594:22)
flutter: #41     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #42     new HttpClient (dart:_http:1594:22)
flutter: #43     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: ...
flutter: ...
flutter: #5982   new HttpClient (dart:_http:1594:22)
flutter: #5983   MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #5984   new HttpClient (dart:_http:1594:22)
flutter: #5985   MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #5986   new HttpClient (dart:_http:1594:22)
flutter: #5987   MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #5988   new HttpClient (dart:_http:1594:22)
flutter: #5989   MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #5990   new HttpClient (dart:_http:1594:22)
flutter: #5991   MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #5992   new HttpClient (dart:_http:1594:22)
flutter: #5993   new IOClient (package:http/src/io_client.dart:23:56)
flutter: #5994   new Client (package:http/src/client.dart:30:27)
flutter: #5995   _withClient (package:http/http.dart:165:20)
flutter: #5996   _AsyncAwaitCompleter.start (dart:async/runtime/libasync_patch.dart:49:6)
flutter: #5997   _withClient (package:http/http.dart:164:25)
flutter: #5998   get (package:http/http.dart:47:3)
flutter: #5999   getContent (file:///.../Workspace/flutter/secure/lib/main.dart:20:26)
flutter: #6000   _AsyncAwaitCompleter.start (dart:async/runtime/libasync_patch.dart:49:6)
flutter: #6001   getContent (file:///.../Workspace/flutter/secure/lib/main.dart:17:26)
flutter: #6002   _MyHomePageState.loadData (file:///.../Workspace/flutter/secure/lib/main.dart:62:5)
flutter: #6003   _AsyncAwaitCompleter.start (dart:async/runtime/libasync_patch.dart:49:6)
flutter: #6004   _MyHomePageState.loadData (file:///.../Workspace/flutter/secure/lib/main.dart:61:16)
flutter: #6005   _MyHomePageState.build.<anonymous closure> (file:///.../Workspace/flutter/secure/lib/main.dart:106:11)
flutter: #6006   _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:494:14)
flutter: #6007   _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:549:30)
flutter: #6008   GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:102:24)
flutter: #6009   TapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:161:9)
flutter: #6010   TapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:123:7)
flutter: #6011   GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:156:27)
flutter: #6012   _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:147:20)
flutter: #6013   _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:121:22)
flutter: #6014   _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:101:7)
flutter: #6015   _WidgetsFlutterBinding&BindingBase&GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:64:7)
flutter: #6016   _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:48:7)
flutter: #6017   _invoke1 (dart:ui/hooks.dart:139:13)
flutter: #6018   _dispatchPointerDataPacket (dart:ui/hooks.dart:96:5)
flutter:
flutter: done!
flutter: Stack Overflow
flutter: #0      MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:8:3)
flutter: #1      new HttpClient (dart:_http:1594:22)
flutter: #2      MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #3      new HttpClient (dart:_http:1594:22)
flutter: #4      MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #5      new HttpClient (dart:_http:1594:22)
flutter: #6      MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #7      new HttpClient (dart:_http:1594:22)
flutter: #8      MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #9      new HttpClient (dart:_http:1594:22)
flutter: #10     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #11     new HttpClient (dart:_http:1594:22)
flutter: #12     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #13     new HttpClient (dart:_http:1594:22)
flutter: #14     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #15     new HttpClient (dart:_http:1594:22)
flutter: #16     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #17     new HttpClient (dart:_http:1594:22)
flutter: #18     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #19     new HttpClient (dart:_http:1594:22)
flutter: #20     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #21     new HttpClient (dart:_http:1594:22)
flutter: #22     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #23     new HttpClient (dart:_http:1594:22)
flutter: #24     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #25     new HttpClient (dart:_http:1594:22)
flutter: #26     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #27     new HttpClient (dart:_http:1594:22)
flutter: #28     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #29     new HttpClient (dart:_http:1594:22)
flutter: #30     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #31     new HttpClient (dart:_http:1594:22)
flutter: #32     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #33     new HttpClient (dart:_http:1594:22)
flutter: #34     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #35     new HttpClient (dart:_http:1594:22)
flutter: #36     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #37     new HttpClient (dart:_http:1594:22)
flutter: #38     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #39     new HttpClient (dart:_http:1594:22)
flutter: #40     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #41     new HttpClient (dart:_http:1594:22)
flutter: #42     MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #43     new HttpClient (dart:_http:1594:22)
flutter: ...
flutter: ...
flutter: #6292   MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #6293   new HttpClient (dart:_http:1594:22)
flutter: #6294   MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #6295   new HttpClient (dart:_http:1594:22)
flutter: #6296   MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #6297   new HttpClient (dart:_http:1594:22)
flutter: #6298   MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #6299   new HttpClient (dart:_http:1594:22)
flutter: #6300   MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #6301   new HttpClient (dart:_http:1594:22)
flutter: #6302   MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #6303   new HttpClient (dart:_http:1594:22)
flutter: #6304   MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #6305   new HttpClient (dart:_http:1594:22)
flutter: #6306   MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #6307   new HttpClient (dart:_http:1594:22)
flutter: #6308   MyHttpOverrides.createHttpClient (file:///.../Workspace/flutter/secure/lib/main.dart:10:16)
flutter: #6309   new HttpClient (dart:_http:1594:22)
flutter: #6310   new IOClient (package:http/src/io_client.dart:23:56)
flutter: #6311   new Client (package:http/src/client.dart:30:27)
flutter: #6312   _withClient (package:http/http.dart:165:20)
flutter: #6313   _AsyncAwaitCompleter.start (dart:async/runtime/libasync_patch.dart:49:6)
flutter: #6314   _withClient (package:http/http.dart:164:25)
flutter: #6315   get (package:http/http.dart:47:3)
flutter: #6316   getContent (file:///.../Workspace/flutter/secure/lib/main.dart:20:26)
flutter: #6317   _AsyncAwaitCompleter.start (dart:async/runtime/libasync_patch.dart:49:6)
flutter: #6318   getContent (file:///.../Workspace/flutter/secure/lib/main.dart:17:26)
flutter: #6319   _MyHomePageState.build (file:///.../Workspace/flutter/secure/lib/main.dart:88:27)
flutter: #6320   StatefulElement.build (package:flutter/src/widgets/framework.dart:3743:27)
flutter: #6321   ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3655:15)
flutter: #6322   Element.rebuild (package:flutter/src/widgets/framework.dart:3508:5)
flutter: #6323   BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2255:33)
flutter: #6324   _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:626:20)
flutter: #6325   _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:208:5)
flutter: #6326   _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15)
flutter: #6327   _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930:9)
flutter: #6328   _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:842:5)
flutter: #6329   _invoke (dart:ui/hooks.dart:125:13)
flutter: #6330   _drawFrame (dart:ui/hooks.dart:114:3)
flutter:


@zoechi zoechi added c: crash Stack traces logged to the console framework flutter/packages/flutter repository. See also f: labels. labels Jul 20, 2018
@zoechi zoechi added this to the Goals milestone Jul 20, 2018
@jonahwilliams
Copy link
Member

Ahh @pepie I made a silly mistake - creating a new HttpClient will call your HttpOverrides which will recurse endlessly. Instead use runZoned like this:

void main() {
  HttpOverrides.runZoned(() {
   runApp(MyApp);
  }, createHttpClient: (SecurityContext _) {
     return new HttpClient();
  });
}

@pepie
Copy link
Author

pepie commented Jul 20, 2018

@jonahwilliams still no luck.
Can you give a sample code showing the usage between main(), HttpOverrides.runZoned() and the MyHttpOverrides() - if this one is still needed?

A few questions:

  1. Given that we've created
class MyHttpOverrides extends HttpOverrides{
  @override
  HttpClient createHttpClient(SecurityContext securityContext){
    return new HttpClient()
    ..badCertificateCallback =(X509Certificate cert, String host, int port) => true;
  }
}

Should your code sample (above) use 'MyHttpOverrides' instead of HttpOverrides?
Oddly enough, MyHttpOverrides.runZoned() returns 'method isn't defined'. I assumed it would have been inherited from 'MyHttpOverrides extends HttpOverrides'.
Anyway, did you intend to say HttpOverride.runZoned() and not
ex:

void main() {
  MyHttpOverrides.runZoned(() {
   runApp(MyApp);
  }, createHttpClient: (SecurityContext _) {
     return new HttpClient();
  });
}

or, are you saying MyHttpOverrides is no longer needed?

2b) Since HttpOverrides.runZoned() creates a new zone, which is different from the root zone, then I guest the following should also work (w/o having to declared MyHttpOverride):

HttpOverrides.runZoned(() {
    runApp(new MyApp());
  }, createHttpClient: (SecurityContext context) {
    return new HttpClient(context: context)
    ..badCertificateCallback =(X509Certificate cert, String host, int port) => true;
  })

But that one failed with 'CERTIFICATE_VERIFY_FAILED'.

I've tried the following (with MyHttpOverrides defined as listed above):
Result: same Stack Overflow result

void main(){
  HttpOverrides.runZoned(() {
    runApp(new MyApp());
  }, createHttpClient: (SecurityContext _context) {
    return new HttpClient();
  });
}

w/ runWithHttpOverrides
Result: same Stack Overflow result

void main(){
  HttpOverrides.**runWithHttpOverrides**((){
    runApp(new MyApp());
  }, new MyHttpOverrides());
;
}

all in one:
Note: This one is returns StackOverflow on first load. But if save the file (to trigger hot reload), I then get CERTIFICATE_VERIFY_FAILED - which means the client callback had no effect.

void main(){
  HttpOverrides.runZoned(() {
    runApp(new MyApp());
  }, createHttpClient: (SecurityContext securityContext) {
    HttpClient _client = HttpClient(context: securityContext);
    _client.badCertificateCallback =(X509Certificate cert, String host, int port) => true;
    return _client;
  });
}

FYI: I've also uninstalled the app cleared the ide (Android Studio) cache several times, to be sure.

@jonahwilliams
Copy link
Member

With the above snippet you should not use HttpOverrides.global or a class that extends HttpOverrides

@pepie
Copy link
Author

pepie commented Jul 21, 2018

@jonahwilliams the runZone option still doesn't work.

This seems to be a major bug, actually.
with

void main() async{
  HttpOverrides.runZoned(() {
    runApp(new App());
  }, createHttpClient: (SecurityContext securityContext) {
    return new HttpClient(context: securityContext)
    ..badCertificateCallback = (X509Certificate cert, String host, int port)=> true;
  });
}

As you mentioned, the fact that HttpClient() is called within createHttpClient is creating an infinite loop. Looking at the code, your first suggestion and the runZoned option had the right intention and should have worked.

It seems either createHttpClient(overrides.dart:100) or the HttpClient factory (http.dart:1589) should keep track of the client instance. Or another method to create a client should be exposed.
overrides.dart:100

  @override
  HttpClient createHttpClient(SecurityContext context) {
    if (_createHttpClient != null) return _createHttpClient(context);
    if (_previous != null) return _previous.createHttpClient(context);
    return super.createHttpClient(context);
  }

http.dart:1589

  factory HttpClient({SecurityContext context}) {
    HttpOverrides overrides = HttpOverrides.current;
    if (overrides == null) {
      return new _HttpClient(context);
    }
    return overrides.createHttpClient(context);
  }

@pepie
Copy link
Author

pepie commented Jul 21, 2018

I just noticed @zoechi flagged this as severe.

@jonahwilliams
Copy link
Member

You're right that doesn't work either. We never hit this because we always used mocks which reimplemented HttpClient. I also tried to use a client created outside of the runZoned scope, but that crashes:

void main() {
  // Temporary debugging hook for https://github.com/flutter/flutter/issues/17956
  debugInstrumentationEnabled = true;
  final HttpClient client = new HttpClient();
  HttpOverrides.runZoned(() {
    new HttpClient();
    runApp(const GalleryApp());
  }, createHttpClient: (SecurityContext context) {
    return client;
  });
}

Stack trace:

[VERBOSE-2:dart_error.cc(16)] Unhandled exception:
Reading static variable 'client' during its initialization
#0      client (file:///Users/jonahwilliams/Documents/Flutter/flutter/examples/flutter_gallery/lib/main.dart:15:7)
#1      main.<anonymous closure> (file:///Users/jonahwilliams/Documents/Flutter/flutter/examples/flutter_gallery/lib/main.dart:30:12)
#2      _HttpOverridesScope.createHttpClient (dart:_http/overrides.dart:103:43)
#3      new HttpClient (dart:_http:1594:22)
#4      client (file:///Users/jonahwilliams/Documents/Flutter/flutter/examples/flutter_gallery/lib/main.dart:15:20)
#5      client (file:///Users/jonahwilliams/Documents/Flutter/flutter/examples/flutter_gallery/lib/main.dart:15:7)
#6      main.<anonymous closure> (file:///Users/jonahwilliams/Documents/Flutter/flutter/examples/flutter_gallery/lib/main.dart:30:12)
#7      _HttpOverridesScope.createHttpClient (dart:_http/overrides.dart:103:43)
#8      new HttpClient (dart:_http:1594:22)
#9      main.<anonymous closure> (file:///U<…>
Syncing files to device iPhone X...                          6.4s

As long as you don't need network assets and images to work (yikes), you could start by creating a top level http client somewhere while we sort this out.

@jonahwilliams jonahwilliams added dependency: dart Dart team may need to help us and removed c: crash Stack traces logged to the console labels Jul 21, 2018
@jonahwilliams
Copy link
Member

@zanderso - is there a proper way to use HttpOverrides, either global or runZoned, such that I can replace the HttpClient without reimplementing it?

@zanderso
Copy link
Member

If you extend HttpOverrides, then in that class super.createHttpClient(context) will give you dart:io's HttpClient. So, for example, if you wanted to intercept all HttpClient calls across an entire app you'd do:

class MyHttpClient implements HttpClient {
  HttpClient _realClient;
  MyHttpClient(this._realClient);
  ...
}

class MyHttpOverrides extends HttpOverrides {
  @override
  HttpClient createHttpClient(SecurityContext context) {
    return new MyHttpClient(super.createHttpClient(context));
  }
}

main() {
  HttpOverrides.global = new MyHttpOverrides();
  ...
}

@jonahwilliams
Copy link
Member

Thank you @zanderso!

@pepie
Copy link
Author

pepie commented Jul 21, 2018

@jonahwilliams @zanderso fantastic!! Thank you for the help.

super.createHttpClient(context) did the trick!

I got it working with the following:

class MyHttpOverrides extends HttpOverrides{
  @override
  HttpClient createHttpClient(SecurityContext context){
    return super.createHttpClient(context)
      ..badCertificateCallback = (X509Certificate cert, String host, int port)=> true;
  }
}

void main(){
    HttpOverrides.global = new MyHttpOverrides();
    runApp(new MyApp());
}

Thank you for the help!

@zoechi
Copy link
Contributor

zoechi commented Jul 21, 2018

Can this issue be closed then?
There is still #13792 for better docs.

@zoechi zoechi added the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Jul 21, 2018
@jonahwilliams
Copy link
Member

Sounds good

@no-response no-response bot removed the waiting for customer response The Flutter team cannot make further progress on this issue until the original reporter responds label Jan 23, 2019
@no-response no-response bot reopened this Jan 23, 2019
@zoechi zoechi closed this as completed Jan 23, 2019
@lifetin
Copy link

lifetin commented Apr 27, 2019

运行
Flutter clean
现在就好了

@junixapp
Copy link

flutter clean not work.

@junixapp
Copy link

junixapp commented Sep 14, 2019

@jonahwilliams @zanderso fantastic!! Thank you for the help.

super.createHttpClient(context) did the trick!

I got it working with the following:

class MyHttpOverrides extends HttpOverrides{
  @override
  HttpClient createHttpClient(SecurityContext context){
    return super.createHttpClient(context)
      ..badCertificateCallback = (X509Certificate cert, String host, int port)=> true;
  }
}

void main(){
    HttpOverrides.global = new MyHttpOverrides();
    runApp(new MyApp());
}

Thank you for the help!

Thank you very very very much, this helped me!

@chunlea
Copy link

chunlea commented Sep 23, 2019

@jonahwilliams @zanderso fantastic!! Thank you for the help.

super.createHttpClient(context) did the trick!

I got it working with the following:

class MyHttpOverrides extends HttpOverrides{
  @override
  HttpClient createHttpClient(SecurityContext context){
    return super.createHttpClient(context)
      ..badCertificateCallback = (X509Certificate cert, String host, int port)=> true;
  }
}

void main(){
    HttpOverrides.global = new MyHttpOverrides();
    runApp(new MyApp());
}

Thank you for the help!

It works with web_socket_channel!

@sameterap
Copy link

It looks that this is working, but what if we want to add our .crt or .pem file. I couldn't make any https requests with them. Can you advice me how to add one of those files to the app and make the https requests ?

I have been struggling with this for a long time. Thanks in advance.

@justintime4tea
Copy link

justintime4tea commented Mar 16, 2020

@sameterap

https://dart-lang.github.io/server/tls-ssl.html#connecting-to-an-https-resource

..setTrustedCertificates(file: 'myTrustedCAs.pem');

https://api.flutter.dev/flutter/dart-io/SecurityContext/setTrustedCertificates.html

@lock
Copy link

lock bot commented Apr 2, 2020

This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

@lock lock bot locked and limited conversation to collaborators Apr 2, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
dependency: dart Dart team may need to help us framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

No branches or pull requests

9 participants