Skip to content

Hyper client hangs #2018

@dawid-nowak

Description

@dawid-nowak

Hey;
I have seen a similar post so perhaps this is a duplicate or perhaps this might have been fixed on the master branch or quite possibly I am doing something that is not right.

I think the code below should be self explanatory and it is a variation of one of your examples. I am doing couple of posts to a server (SpringBoot java returns empty body with no processing). First two calls work fine. client_with_requests never terminates hyper::rt::run(f1). Similarly fetch_url_with_client never terminates. Cargo dependencies are at the bottom of the post.

Just to add that everything works fine when keep_alive flag is set to false.

extern crate futures;
extern crate hyper;
#[macro_use]
extern crate log;

use http::HeaderValue;
use hyper::{Body, Request, Client};
use hyper::client::connect::dns::GaiResolver;
use hyper::client::HttpConnector;
use hyper::rt::{Future, Stream};

fn main() {
    env_logger::init();

    let url = "http://127.0.0.1:9999/response".parse::<hyper::Uri>().unwrap();

    hyper::rt::run(fetch_url(url.clone()));
    info!("1 done");
    hyper::rt::run(fetch_url(url.clone()));
    info!("2 done");


    client_with_requests(url.clone());
    info!("We should see this");

    let client = hyper::Client::builder().keep_alive(true).build_http();
    hyper::rt::run(fetch_url_with_client(url.clone(), client.clone()));
    info!("We should see this");

}

fn fetch_url(url: hyper::Uri) -> impl Future<Item=(), Error=()> {
    let client = hyper::Client::builder().keep_alive(true).build_http();

    let req = Request::builder()
         .method("POST")
         .uri(url)
         .header(hyper::header::CONTENT_TYPE,HeaderValue::from_static("application/json"))
         .body(Body::from("{\"Hallo\":\"hallo\"}"))
         .expect("request builder");

    client.request(req)
        .and_then(|res| {
         info!("POST: {}", res.status());
         res.into_body().concat2()
    })
        // If all good, just tell the user...
        .map(|_| {
            println!("Done.");
        })
        // If there was an error, let the user know...
        .map_err(|err| {
            eprintln!("Error {}", err);
        })
}


fn fetch_url_with_client(url: hyper::Uri, client:Client<HttpConnector<GaiResolver>>) -> impl Future<Item=(), Error=()> {
    let req = Request::builder()
        .method("POST")
        .uri(url)
        .header(hyper::header::CONTENT_TYPE,HeaderValue::from_static("application/json"))
        .body(Body::from("{\"Hallo\":\"hallo\"}"))
        .expect("request builder");


    client.request(req)
        .and_then(|res| {
            info!("POST: {}", res.status());
            res.into_body().concat2()
        })
        // If all good, just tell the user...
        .map(|_| {
            println!("Done fetch with client.");
        })
        // If there was an error, let the user know...
        .map_err(|err| {
            eprintln!("Error {}", err);
        })
}


fn client_with_requests(url: hyper::Uri)  {
    let client = hyper::Client::builder().keep_alive(true).build_http();
    let req1 = Request::builder()
        .method("POST")
        .uri(url.clone())
        .header(hyper::header::CONTENT_TYPE,HeaderValue::from_static("application/json"))
        .body(Body::from("{\"Hallo\":\"hallo\"}"))
        .expect("request builder");

    let req2 = Request::builder()
        .method("POST")
        .uri(url.clone())
        .header(hyper::header::CONTENT_TYPE,HeaderValue::from_static("application/json"))
        .body(Body::from("{\"Hallo\":\"hallo\"}"))
        .expect("request builder");


    let f1 = client.request(req1)
        .and_then(|res| {
            info!("POST: {}", res.status());
            res.into_body().concat2()
        })
        // If all good, just tell the user...
        .map(|_| {
            println!("Done fetch with client 1");
        })
        // If there was an error, let the user know...
        .map_err(|err| {
            eprintln!("Error {}", err);
        });
    let f2 = client.request(req2)
        .and_then(|res| {
            info!("POST: {}", res.status());
            res.into_body().concat2()
        })
        // If all good, just tell the user...
        .map(|_| {
            println!("Done fetch with client 2");
        })
        // If there was an error, let the user know...
        .map_err(|err| {
            eprintln!("Error {}", err);
        });

    hyper::rt::run(f1);
    hyper::rt::run(f2)
}

Cargo dependencies

[dependencies]
pretty_env_logger=""
futures = "0.1"
http = "0.1"
hyper = "0.12"
tokio-io = "0.1.1"
tokio-rustls = "0.7"
tokio-tcp = "0.1"
webpki = "0.18.1"
webpki-roots = "0.15"
tokio = "0.1"
log = "0.4"
env_logger = "*"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions