I have a simple HTTP server using Router and Iron on port 3005. It is not doing anything exciting. I believe it just echoes back the request, but the details are not important.
I have also made a simple client using hyper's client module to send requests to the server.
Whenever I run the server on IPv4 localhost
, I experience no issues. I can query it both with my client and with curl. If I start the server on my IPv6 localhost
(I am using the shortened version ::1
), I am only able to access the server with curl.
This indicates that the server is running properly and responding, but my hyper Client
code to access it fails, reporting:
Err(Io(Error { repr: Custom(Custom { kind: Other, error: StringError("failed to lookup address information: Name or service not known") }) })) thread 'main' panicked at 'called
Result::unwrap()
on anErr
value: Io(Error { repr: Custom(Custom { kind: Other, error: StringError("failed to lookup address information: Name or service not known") }) })', /checkout/src/libcore/result.rs:860
The code I use to send the POST request is as follows:
let addr = "http://[::1]:3005/message";
let mut res = self.client.post(addr).body(s.as_str()).send().unwrap();
Where s
is some payload I am sending.
I have tried the expanded IPv6 address as well ([0:0:0:0:0:0:0:1]
) and I get the same error.
I have also tried both the shortened and the expanded IPv6 addresses without the brackets. I get "invalid port -" with the expanded address and "Empty Host" with the shortened.
To reproduce this behaviour, you can use these small examples (uncomment the commented lines to recieve the error):
Server
extern crate iron;
use iron::prelude::*;
use iron::status;
fn hello_world(_: &mut Request) -> IronResult<Response> {
println!("Recvd a request");
Ok(Response::with((status::Ok, "Hello World!")))
}
fn main() {
let port = 3000;
//let addr = format!("{}:{}", "[::1]", port);
let addr = format!("{}:{}", "localhost", port);
println!("Server opened on {}", addr);
Iron::new(hello_world).http(addr).unwrap();
}
Client
// hyper 0.10.13
extern crate hyper;
use hyper::*;
use std::io::Read;
fn main() {
let client = Client::new();
//let mut res = client.get("http://[::1]:3000/").send().unwrap();
let mut res = client.get("http://localhost:3000/").send().unwrap();
let mut s = String::new();
res.read_to_string(&mut s).unwrap();
println!("response contained: {}", s);
}
ClientV2
// For people that want to try with hyper 0.11.X
extern crate futures;
extern crate hyper;
extern crate tokio_core;
use std::io::{self, Write};
use futures::{Future, Stream};
use hyper::Client;
use tokio_core::reactor::Core;
fn main() {
let mut core = Core::new().unwrap();
let client = Client::new(&core.handle());
let uri = "http://[::1]:3000/".parse().unwrap();
let work = client.get(uri).and_then(|res| {
println!("Response: {}", res.status());
res.body().for_each(|chunk| {
io::stdout()
.write_all(&chunk)
.map(|_| ())
.map_err(From::from)
})
});
core.run(work).unwrap();
}
Note1:
You need hyper 0.10.X in order to get this code running. In my case I was using 0.10.13
Note2:
I am sending GET requests with no payload, in order to abstract out the irrelevant bits of functionality.
Note3:
It seems like hyper 0.10.X and hyper 0.11.X handle the IPv6 server differently. Hyper 0.10.X gives the aforementioned error, while 0.11.X gives me Response Code 400 Bad Request.