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

add Timeout functionality for http package #21

Open
DartBot opened this issue Jun 5, 2015 · 25 comments
Open

add Timeout functionality for http package #21

DartBot opened this issue Jun 5, 2015 · 25 comments
Labels
type-enhancement A request for a change that isn't a bug

Comments

@DartBot
Copy link

DartBot commented Jun 5, 2015

Originally opened as dart-lang/sdk#19831

This issue was originally filed by [email protected]


What steps will clearly show the issue / need for enhancement?

  1. when making http requests you usually want to timeout the request after a reasonable amount of time (usually in the region of seconds)
  2. it would be great to have away to specify timeout as Duration when making a http request via the http/browser client/http client classes.

What version of the product are you using? On what operating system?
Dart 1.5.1, http 0.11.1+1

@DartBot
Copy link
Author

DartBot commented Jun 5, 2015

<img src="https://avatars.githubusercontent.com/u/2108507?v=3" align="left" width="48" height="48"hspace="10"> Comment by dgrove


Added Pkg-Http, Triaged labels.

@DartBot DartBot added the type-enhancement A request for a change that isn't a bug label Jun 5, 2015
@DartBot
Copy link
Author

DartBot commented Jun 5, 2015

<img src="https://avatars.githubusercontent.com/u/188?v=3" align="left" width="48" height="48"hspace="10"> Comment by nex3


Probably the best way to support this would be to add a separate http_timeout_client package that exposes an HttpTimeoutClient that wraps an existing client.

@DartBot
Copy link
Author

DartBot commented Jun 5, 2015

This comment was originally written by [email protected]


Is there any reason why timeout couldn't be added as an optional parameter to the existing clients? I think the usage pattern would be more obvious this way than having to first create a client, then create another (HttpTimeoutClient) to wrap around it before you do a HTTP request.

@DartBot
Copy link
Author

DartBot commented Jun 5, 2015

<img src="https://avatars.githubusercontent.com/u/188?v=3" align="left" width="48" height="48"hspace="10"> Comment by nex3


The http package is based on a composition model where each layer (that is, a class implementing http.Client) is very simple and has a well-defined purpose. This model makes it very easy to mix and match functionality, but one of the costs is that the API for a layer has to be very simple in order to keep them easy to implement. It would be bad if everyone implementing their own [http.Client] had to re-implement the timeout logic from scratch.

having to first create a client, then create another (HttpTimeoutClient) to wrap around it before you do a HTTP request.

The API wouldn't be that difficult. The constructor would look something like this:

    HttpTimeoutClient([HttpClient inner])
        : _inner = inner == null ? new HttpClient() : inner;

The user only needs to construct one client if they only care about one aspect of the client.

@DartBot
Copy link
Author

DartBot commented Jun 5, 2015

This comment was originally written by [email protected]


Hi, thanks for the explanation, that makes a lot of sense.

@DartBot
Copy link
Author

DartBot commented Jun 5, 2015

<img src="https://avatars.githubusercontent.com/u/188?v=3" align="left" width="48" height="48"hspace="10"> Comment by nex3


Issue #10 has been merged into this issue.

@DartBot
Copy link
Author

DartBot commented Jun 5, 2015

<img src="https://avatars.githubusercontent.com/u/444270?v=3" align="left" width="48" height="48"hspace="10"> Comment by seaneagan


Doesn't Future.timeout solve this pretty well already?

https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart-async.Future#id_timeout

Example:

    http.read('http://google.com')
        .timeout(const Duration(seconds: 5))
        .then(...);

@DartBot
Copy link
Author

DartBot commented Jun 5, 2015

<img src="https://avatars.githubusercontent.com/u/17034?v=3" align="left" width="48" height="48"hspace="10"> Comment by kevmoo


I don't think HttpTimeoutClient can accomplish what we want.

Users would like to actually cancel the inflight request.

dart:html has abort() on HttpRequest
dart:io HttpClient* has no equivalente – the idleTimeout just manages keep-alive connections while idea AKAICT


Added Area-Pkg label.

@DartBot
Copy link
Author

DartBot commented Jun 5, 2015

<img src="https://avatars.githubusercontent.com/u/17034?v=3" align="left" width="48" height="48"hspace="10"> Comment by kevmoo


Marked this as being blocked by dart-lang/sdk#22265.

@tomyeh
Copy link

tomyeh commented Aug 18, 2017

Any plan to support it?

@donny-dont
Copy link

This can easily be done through a middleware with the 0.12 implementation.

@donny-dont
Copy link

@nex3 there's also HttpRequest.timeout which we could have a special context for. We might also want to handle the onTimeout if that's the case.

@xqwzts
Copy link

xqwzts commented Oct 11, 2017

@donny-dont Could you clarify how one could do this as a middleware?

@jimmyshiau
Copy link

@donny-dont
Is any way to set timeout for HttpClient on server side?

@butlermatt
Copy link

This is sorely needed on the server side. Currently I have a request that establishes connection, but the remote server hangs for 10 minutes before it gives up and closes the connection.
The issue is that the connection is established and (in theory) at least some header information is started. As a result the Client.get is blocking. So adding a timeout to the future doesn't work.

So I have something like:

try {
    var resp = await Client.get(uri, headers: h).timeout(new Duration(seconds: 10));
} catch (e) {
    log.warning('Request failed', e);
}

After 10 minutes I get the timeout exception, plus a warning that "the remote server closed connection before all headers were receive". Because the connection itself is established, the timeout on the future isn't trigged until the next event loop, but because the loop is blocked for 10 minutes it's essentially useless.

@nex3
Copy link
Member

nex3 commented Dec 7, 2017

@butlermatt Under no circumstances should this ever be blocking. It shouldn't be able to block unless something very strange is going on in dart:io. I'd suggest seeing if you can reproduce that with pure dart:io code and then filing an issue against the SDK.

@Nitin-Harman
Copy link

Nitin-Harman commented Jan 24, 2018

try {
var resp = await Client.get(uri, headers: h).timeout(new Duration(seconds: 10));
} catch (e) {
log.warning('Request failed', e);
} .
How can i remove timeout from this code.becuase timeout is depend on network call and without timeout it gives error.

@carmas123
Copy link

Please add ability to split timeout connect from timeout read.

@natebosch
Copy link
Member

@carmas123 - I don't believe it's possible to set a connect timeout in the dart:html code path so a setting would not be appropriate for this package as it works across both.

Assuming you're using this with dart:io (flutter or VM) you should be able to do it manually.

Construct an IOCLient and pass in an explicitly constructed HttpClient. On that inner client you can set the connectionTimeout

@carmas123
Copy link

Very good thank you

@thenotoriousdev
Copy link

thenotoriousdev commented Apr 19, 2019

Hello what is finally the solution to using the timeout with http (get/post methods) package. Can I please get an example?

@alexgarciaju
Copy link

Any news on this? @thenotoriousdev

@venkatesh-u
Copy link

venkatesh-u commented Dec 27, 2019

I try to increase the time out as per my server response, but it's timing out after 1min.
How to increase timeout?
Below is my code, Could you please look into it

  HttpClient httpClient = new HttpClient();
  httpClient.connectionTimeout = Duration(seconds: 600);
  HttpClient.enableTimelineLogging = true;
  HttpClientRequest request = await httpClient.postUrl(Uri.parse(url));
  request.headers.set('content-type', 'application/json');
  request.add(utf8.encode(json.encode(params)));
  HttpClientResponse response = await request.close().timeout(const Duration(seconds: 600));
  httpClient.close();
  if (response.statusCode == 200) //Handle response

@droplet-js
Copy link

any news update?

I just wonder how to set 'writeTimeout'. Can you help me?

  Future<File> _downloadFile(
    HttpClient client,
    String url,
    File saveFile, {
    Duration readTimeout = const Duration(seconds: 10),
  }) async {
    final HttpClientRequest req = await client.getUrl(Uri.parse(url));
    // await req.addStream(Stream<List<int>>.empty());//.timeout(timeLimit/*writeTimeout*/); ???
    final HttpClientResponse resp = await req.close();//.timeout(timeLimit/*requestTimeout*/);
    print('${resp.statusCode} - ${resp.reasonPhrase}');
    if (resp.statusCode == HttpStatus.ok) {
      final Stopwatch watch = Stopwatch()..start();
      IOSink? sink;
      try {
        saveFile.createSync(recursive: true);
        sink = saveFile.openWrite();
        await sink.addStream(resp.timeout(readTimeout/*readTimeout*/));//.timeout(timeLimit/*receiveTimeout*/);
        await sink.close();
      } catch (e) {
        print(e);
        await sink?.close();
        if (saveFile.existsSync()) {
          await saveFile.delete();
        }
      } finally {
        watch.stop();
        print('elapsed: ${watch.elapsed}');
      }
    } else {
      throw HttpException('${resp.statusCode} - ${resp.reasonPhrase}', uri: req.uri);
    }
    return saveFile;
  }

  HttpClient _serverClient({
    Duration connectTimeout = const Duration(seconds: 10),
  }) {
    final HttpClient client = HttpClient();
    client.connectionTimeout = connectTimeout; // connectTimeout
    return client;
  }

@fatadel
Copy link

fatadel commented Dec 6, 2021

If anyone wants a simple connection timeout and uses this package only with dart VM (so, dart io client internally) then I think the best solution would be like this:

import 'dart:io';

import 'package:http/io_client.dart' as http;
import 'package:http/retry.dart';

RetryClient( // the usual client or say for example RetryClient
        http.IOClient(HttpClient()..connectionTimeout = Duration(seconds: 5)),
);

It's also possible to set a session timeout with the same approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-enhancement A request for a change that isn't a bug
Projects
None yet
Development

No branches or pull requests