dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.09k stars 1.56k forks source link

Feature request: HttpClient should accept existing Socket objects to establish the connection #43277

Closed zichangg closed 2 years ago

zichangg commented 4 years ago

HttpClient is not able to reuse existing sockets. It will always use _SecureSocket or _Socket (dart:io implementation of SecureSocket/Socket). Self-written Sockets are not allowed. Users will have to use IOOverride as a workaround.

With this feature, it grants the freedom to users to choose the underlying connection. e.g. Unix domain sockets, which was supported a while ago, can be easily installed to HttpClient.

It also potential boosts the performance if used properly.

hacker1024 commented 3 years ago

IOOverride does not even allow overriding SecureSocket.startConnect or SecureSocket.connect, so there's no workaround at all to use a custom socket with HTTPS.

inst-cicada commented 3 years ago

@zichangg can you please elaborate the problem? The one I am getting is that if you are unable to use existing sockets for eg. you are getting error wile connecting with locally hosted API and getting Socket Exception Error. Then to fix those issue follow the steps given below:

1. Open Android Studio and open your Flutter Project. 2. Start your Android Emulator. 3. Start your API in local server and note the host url along with port. e.g. http://xxx.xxx.xx.x:5000 4. After hosting the API open Command Line and run the following code: `adb reverse tcp: tcp:` eg. suppose you have hosted your api in http://xxx.xxx.xx.x:5000 then put 5000 in and use http://xxx.xxx.xx.x:5000 in HttpClient to get or post. 5. Go to your dart file and run the code. It worked for me. Sorry If I got your problem wrong. I'm new to developing so. And if I got it right. Cheers.
brianquinlan commented 2 years ago

I have a design proposal to tackle this issue. Any feedback would be welcome: https://docs.google.com/document/d/1W8TsGXQheNrxQSulr1S3BscZ_ncUsXuPhpAlTsp6lsU/edit#heading=h.xgjl2srtytjt

brianquinlan commented 2 years ago

I'm going to mark this as fixed by a0aeed9faad4c793c7679db3b8eed58ab1be6d5c - if that is not sufficient, please reopen.

hacker1024 commented 2 years ago

@brianquinlan

I'm trying to use the solution added on a0aeed9 to use a SSL HTTP(S) proxy.

I have built SDK revision 9863451 with d6a4eda reverted.

final client = IOClient(HttpClient()
  ..findProxy = ((_) => 'PROXY username:password@au755.nordvpn.com:89')
  ..connectionFactory = ((url, proxyHost, proxyPort) {
    // I'm assuming a SSL proxy is provided here for the sake of simplicity.
    return SecureSocket.startConnect(proxyHost!, proxyPort!);
  }));
await client.read(Uri.parse('https://dart.dev'))

This fails with the following error:

Unhandled exception:
NoSuchMethodError: Class '_RawSocket' has no instance getter 'closedReadEventSent'.
Receiver: Instance of '_RawSocket'
Tried calling: closedReadEventSent
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:38:5)
#1      new _RawSecureSocket (dart:io/secure_socket.dart:527:21)
#2      _RawSecureSocket.connect (dart:io/secure_socket.dart:469:16)
#3      RawSecureSocket.secure (dart:io/secure_socket.dart:289:29)
#4      SecureSocket.secure.<anonymous closure> (dart:io/secure_socket.dart:110:30)
<asynchronous suspension>
#5      _HttpClient._openUrl.<anonymous closure> (dart:_http/http_impl.dart:2721:15)
<asynchronous suspension>

The error happens after the authentication stage; if the credentials are wrong, I receive an HTTP 407 error from the proxy server.

It's also worth noting that replacing https://dart.dev with a plaintext HTTP website works just fine.

brianquinlan commented 2 years ago

Hi @hacker1024 - if you change the code to not use connectionFactory does this work? ie

final client = IOClient(HttpClient()
  ..findProxy = ((_) => 'PROXY username:password@au755.nordvpn.com:89');
await client.read(Uri.parse('https://dart.dev'))

If so, could you file another bug to track this issue?

hacker1024 commented 2 years ago

@brianquinlan It does not. See: #43876.