hyperium / hyper

An HTTP library for Rust
https://hyper.rs
MIT License
14.58k stars 1.6k forks source link

Request timeouts #1097

Closed crackcomm closed 7 years ago

crackcomm commented 7 years ago

Is it possible to configure request or HTTP client timeouts? I am interested in master/tokio branch.

seanmonstar commented 7 years ago

As of now, there isn't specific timeouts to set that are inside hyper. There are a few reasons why, but the main reason was because using futures makes it quite simple for anyone to deal with timeouts external to hyper. For example:

let timeout = tokio_core::reactor::Timeout::new(Duration:from_secs(30), &handle))?;
// a tokio timeout doesn't necessarily mean an error,
//  but in our case, always make it an error
// (it could also be used for things like "send this message after this amount of time")
let timeout = timeout.then(|_| Err(io::Error::new(io::ErrorKind::TimedOut, "our timeout")));
// set up our client request
let future_body = client.get(some_url).and_then(|res| {
    res.body().fold(Vec::new(), |mut vec, chunk| {
        vec.extend_from_slice(&chunk);
        Ok(vec)
    })
});

// select on the request and the timeout
// the first one to 'complete' will trigger our callback
// since we converted the timeout to always be an error,
// it will only ever be in the `Err` variant
let work = future_body.select(timeout).then(|result| {
    match result { 
        Ok(body) => {
            // do something with the body
        },
        Err(e) => {
            // could be an http  or io error (including our time out error)
            // inspect to find out which it was
        }
    }
});
handle.spawn(work);
crackcomm commented 7 years ago

Thanks, that explains a lot. I can't see any correlation between timeouts and request, how can I ensure that request is cancelled after timeout?

carllerche commented 7 years ago

If the request future is dropped, then that can trigger a cancellation. The example with select above will drop the request future if the timeout competes first. That is how the request is cancelled. On Sun, Mar 19, 2017 at 10:55 AM Łukasz Kurowski notifications@github.com wrote:

Thanks, that explains a lot. I can't see any correlation between timeouts and request, how can I ensure that request is cancelled after timeout?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/hyperium/hyper/issues/1097#issuecomment-287634290, or mute the thread https://github.com/notifications/unsubscribe-auth/AAAYJALkjAv9KTabGbGlLPWdx8nj6mgxks5rnWwTgaJpZM4MhxZh .

crackcomm commented 7 years ago

@carllerche this is a great mechanism, thank you for this explanation and @seanmonstar thank you for this example.

Trenson commented 5 years ago

As of now, there isn't specific timeouts to set that are inside hyper. There are a few reasons why, but the main reason was because using futures makes it quite simple for anyone to deal with timeouts external to hyper. For example:

let timeout = tokio_core::reactor::Timeout::new(Duration:from_secs(30), &handle))?;
// a tokio timeout doesn't necessarily mean an error,
//  but in our case, always make it an error
// (it could also be used for things like "send this message after this amount of time")
let timeout = timeout.then(|_| Err(io::Error::new(io::ErrorKind::TimedOut, "our timeout")));
// set up our client request
let future_body = client.get(some_url).and_then(|res| {
    res.body().fold(Vec::new(), |mut vec, chunk| {
        vec.extend_from_slice(&chunk);
        Ok(vec)
    })
});

// select on the request and the timeout
// the first one to 'complete' will trigger our callback
// since we converted the timeout to always be an error,
// it will only ever be in the `Err` variant
let work = future_body.select(timeout).then(|result| {
    match result { 
        Ok(body) => {
            // do something with the body
        },
        Err(e) => {
            // could be an http  or io error (including our time out error)
            // inspect to find out which it was
        }
    }
});
handle.spawn(work);

Hello, I found your code have compile error. let work = future_body.select(timeout).then(|result| { | ^^^^^^ expected struct std::io::Error, found struct hyper::Error

rafrafek commented 1 year ago

Will slow download trigger timeout?