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

IsahcClient created without Config ignores the timeout setting. #102

Open
trrk opened this issue Apr 10, 2022 · 0 comments
Open

IsahcClient created without Config ignores the timeout setting. #102

trrk opened this issue Apr 10, 2022 · 0 comments
Labels
bug Something isn't working

Comments

@trrk
Copy link

trrk commented Apr 10, 2022

IsahcClient::new() creates a client with a timeout set to 60 seconds. However, this client does not actually return a timeout error after 60 seconds. IsahcClient created with Config and try_into does not have this problem and returns a timeout error after 60 seconds.


Here are some additional explanations.

  • There is a concern related to this IsahcClient timeout issue. It is possible that settings other than timeout are also being ignored. Other clients may also have this issue.
  • I noticed this problem while using surf. The timeout behavior was different for the two below.
let client: Client = Config::new()
            .try_into()
            .unwrap();
client.get("...").send().await;

surf::get("...").send().await;
  • Here is the code I used to check the behavior. It takes more than 60 seconds to run. Depending on the environment, it may not work as expected.
use async_std::task;
use futures::prelude::*;
use http_client::{isahc, Config, HttpClient};
use std::time::Duration;

#[async_std::main]
async fn main() {
    let mut tasks = vec![];

    tasks.push(task::spawn(async {
        let client: isahc::IsahcClient = Config::new()
            .try_into()
            .unwrap();
        assert_eq!(client.config().timeout, Some(Duration::from_secs(60)));

        run_test(client, "isahc: created with config").await;
    }));
    tasks.push(task::spawn(async {
        let client = isahc::IsahcClient::new();
        assert_eq!(client.config().timeout, Some(Duration::from_secs(60)));

        run_test(client, "isahc: created by new()").await;
    }));

    println!("start tasks");
    future::join_all(tasks).await;
}

async fn run_test(client: impl HttpClient, process_name: &str) {
    let timeout = client.config().timeout.unwrap();
    let sleep_duration = timeout + Duration::from_secs(1);

    let result = communicate(client, sleep_duration).await;

    let timeout_secs = timeout.as_secs();
    let sleep_secs = sleep_duration.as_secs();
    println!(
        "{process_name}: config.timeout={timeout_secs} sleep={sleep_secs} result={:?}",
        result
    );
}

// Make a request to the server. Then read the body after the specified time has elapsed. Created to cause a timeout.
// If communication is successful, return Ok. Otherwise (including a timeout), return Err.
async fn communicate(client: impl HttpClient, sleep_duration: Duration) -> Result<(), std::io::Error> {
    // If the body is to be read internally to the end, the size must be increased. Otherwise, it will not time out.
    const BODY_BYTES: usize = 80 * 1024;

    let url = format!("http://httpbin.org/bytes/{BODY_BYTES}");
    let url = http_types::Url::parse(&url).unwrap();

    let req = http_types::Request::get(url);
    let mut res = client.send(req).await.unwrap();

    let mut body = res.take_body().into_reader();

    task::sleep(sleep_duration).await;

    let mut total = vec![];
    let read_bytes = body.read_to_end(&mut total).await?;

    assert_eq!(read_bytes, BODY_BYTES);
    Ok(())
}
isahc: created with config: config.timeout=60 sleep=61 result=Err(Kind(TimedOut))
isahc: created by new(): config.timeout=60 sleep=61 result=Ok(())
@Fishrock123 Fishrock123 added the bug Something isn't working label May 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants