Hyper uri encoded

I have

let url = "http://127.0.0.1:80/docs".parse::<hyper::Uri>()?;

I get a response from the server 404 Not Found

I see a request in the server logs "GET http%3A//127.0.0.1%3A80/docs HTTP/1.1" 404 Not Found

I'm just learning rust. I'm studying tokio and hyper. What am I doing wrong?

That's creating an Uri but how are you using it to make your request?

I am studying an example from the hyper page

    // Parse our URL...
    let url = "http://127.0.0.1:80/docs".parse::<hyper::Uri>()?;

    // Get the host and the port
    let host = url.host().expect("uri has no host");
    let port = url.port_u16().unwrap_or(80);
    let path = url.path();
    let scheme = url.scheme_str().expect("uri has no scheme");
    println!("scheme: {}", &scheme);
    println!("host: {}", &host);
    println!("port: {}", &port);
    println!("path: {}", &path);

    let address = format!("{}:{}", host, port);

    // Open a TCP connection to the remote host
    let stream = TcpStream::connect(address).await?;

    // Use an adapter to access something implementing `tokio::io` traits as if they implement
    // `hyper::rt` IO traits.
    let io = TokioIo::new(stream);

    // Perform a TCP handshake
    let (mut sender, conn) = hyper::client::conn::http1::handshake(io).await?;

    // Spawn a task to poll the connection, driving the HTTP state
    tokio::task::spawn(async move {
        if let Err(err) = conn.await {
            println!("Connection failed: {:?}", err);
        }
    });

    // The authority of our URL will be the hostname of the httpbin remote
    let authority = url.authority().unwrap().clone();

    // Create an HTTP request with an empty body and a HOST header
    let req = Request::builder()
        .uri(url)
        .header(hyper::header::HOST, authority.as_str())
        .body(Empty::<Bytes>::new())?;

    // Await the response...
    let mut res = sender.send_request(req).await?;

    println!("Response status: {}", res.status());

    // Stream the body, writing each frame to stdout as it arrives
    while let Some(next) = res.frame().await {
        let frame = next?;
        if let Some(chunk) = frame.data_ref() {
            stdout().write_all(&chunk).await?;
        }
    }

I discovered the following moment:

From the application on rust in the server logs, an entry of the following type 172.17.0.1:49990 - "POST /api/v1/report/base_metrics HTTP/1.1" 200 OK

From the application on python in the server logs, an entry of the following type 172.17.0.1:45980 - "GET http%3A//127.0.0.1%3A80/docs HTTP/1.1" 404 Not Found

scheme, host and port come as part of the path.

I don't know if I found the right solution, but if I pass the path to the uri instead of the url, then everything works correctly.

let req = Request::builder()
        .uri(path)
        .header(hyper::header::HOST, authority.as_str())
        .body(Empty::<Bytes>::new())?;
1 Like