Search code examples
httptcprustipv6

How to use IF_INET6 - IPV6 when sending a HTTP request in Rust


I am trying to send a HTTP request with IPv6.

While there are a lot of HTTP libraries (reqwest, hyper, etc). I couldn't find a library or a way to send a request with it.

In python, i was able to specify TCP family class with creating a custom TCPConnector.

import aiohttp
import socket

conn = aiohttp.TCPConnector(family=socket.AF_INET6)

I looked through the same TCPConnector, ClientBuilder things in Rust.

Reqwest's ClientBuilder doesn't supports it. See: https://docs.rs/reqwest/0.11.0/reqwest/struct.ClientBuilder.html

Hyper's HTTPConnector also doesn't supports it. See: https://docs.rs/hyper/0.14.4/hyper/client/struct.HttpConnector.html


Solution

  • It is not obvious but if you specify the local_address option, the connection will use that ip address to send the request.

    I use Reqwest (v0.11.1 in the example) now.

    use std::net::IpAddr;
    use std::{collections::HashMap, str::FromStr};
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
        let client = reqwest::Client::builder()
            .local_address(IpAddr::from_str("2001:0db8:85a3:0000:0000:8a2e:0370:7334")?) 
            .build()?;
    
        let resp = client
            .get("https://httpbin.org/ip")
            .send()
            .await?
            .json::<HashMap<String, String>>()
            .await?;
    
        println!("{:#?}", resp);
        Ok(())
    }
    
    

    This also works i but i prefer reqwest now.

    Fortunately, i found a HTTP library called isahc library that i can specify IP version.

    use isahc::{config::IpVersion, prelude::*, HttpClient};
    
    HttpClient::builder()
        .ip_version(IpVersion::V6)
    

    Isahc's isahc::HttpClientBuilder struct has ip_version method that you can specify IP version. (see)

    use isahc::{config::IpVersion, prelude::*, HttpClient};
    use std::{
        io::{copy, stdout},
        time::Duration,
    };
    
    fn main() -> Result<(), isahc::Error> {
        let client = HttpClient::builder()
            .timeout(Duration::from_secs(5))
            .ip_version(IpVersion::V6)
            .build()?;
    
        let mut response = client.get("some url")?;
    
        copy(response.body_mut(), &mut stdout())?;
    
        Ok(())
    }