mio_httpc is an async http client that runs on top of mio only.
No call will block, not even for DNS resolution as it is implemented internally to avoid blocking.
It uses http crate for Request/Response types.
mio_httpc requires you specify one of the TLS implementations using features: rustls, native, openssl. Not picking any feature will NOT work, as all calls will be no-op.
WARNING
openssl and native backends work well.
rustls is unreliable at the moment. I'm not sure if the issue is rustls or tls-api-rustls.
TODO
EXAMPLES
Basic get
cargo run --example get --features "native" -- "https://edition.cnn.com"
extern crate mio_httpc;
extern crate mio;
use mio_httpc::{Request,CallBuilder,Httpc,SimpleCall};
use mio::{Poll,Events};
fn main() {
let poll = Poll::new().unwrap();
let mut htp = Httpc::new(10);
let mut req = Request::builder();
let args: Vec<String> = ::std::env::args().collect();
let req = req.uri(args[1].as_str()).body(Vec::new()).expect("can not build request");
let call = CallBuilder::new(req).timeout_ms(500).call(&mut htp, &poll).expect("Call start failed");
let mut call = SimpleCall::from(call);
let to = ::std::time::Duration::from_millis(100);
'outer: loop {
let mut events = Events::with_capacity(8);
poll.poll(&mut events, Some(to)).unwrap();
for cref in htp.timeout().into_iter() {
if call.is_ref(cref) {
println!("Request timed out");
break 'outer;
}
}
for ev in events.iter() {
let cref = htp.event(&ev);
if call.is_call(&cref) {
if call.perform(&mut htp, &poll).expect("Call failed") {
let mut resp = call.close().expect("No response");
let v = mio_httpc::extract_body(&mut resp);
if let Ok(s) = String::from_utf8(v) {
println!("Body: {}",s);
}
break 'outer;
}
}
}
}
}
Websockets
cargo run --example ws --features="native" -- "wss://demos.kaazing.com/echo"
extern crate mio_httpc;
extern crate mio;
use mio_httpc::{Request,CallBuilder,Httpc,WebSocket,WSPacket};
use mio::{Poll,Events};
fn main() {
let poll = Poll::new().unwrap();
let mut htp = Httpc::new(10);
let mut req = Request::builder();
let args: Vec<String> = ::std::env::args().collect();
let req = req.uri(args[1].as_str()).body(Vec::new()).expect("can not build request");
let mut ws = CallBuilder::new(req).websocket(&mut htp, &poll).expect("Call start failed");
let to = ::std::time::Duration::from_millis(800);
'outer: loop {
let mut events = Events::with_capacity(8);
poll.poll(&mut events, Some(to)).unwrap();
for cref in htp.timeout().into_iter() {
if ws.is_ref(cref) {
println!("Request timed out");
break 'outer;
}
}
if events.len() == 0 {
println!("send yo");
ws.send_text(true, "yo!");
}
for ev in events.iter() {
let cref = htp.event(&ev);
if ws.is_call(&cref) {
if ws.is_active() {
match ws.recv_packet(&mut htp, &poll).expect("Failed recv") {
WSPacket::Pong(_) => {
println!("Got pong!");
}
WSPacket::Ping(_) => {
println!("Got ping!");
ws.pong(None);
}
WSPacket::None => {}
WSPacket::Close(_,_) => {
println!("Got close!");
ws.close(None, None);
break 'outer;
}
WSPacket::Text(fin,txt) => {
println!("Got text={}, fin={}",txt,fin);
}
WSPacket::Binary(fin,b) => {
println!("Got bin={}B, fin={}",b.len(),fin);
}
}
} else {
if ws.sendq_len() == 0 {
ws.ping(None);
}
}
}
}
ws.perform(&mut htp, &poll).expect("Call failed");
}
ws.perform(&mut htp, &poll);
ws.finish(&mut htp);
}