mio_httpc is an async http client that runs on top of mio only.

For convenience it also provides CallBuilder::exec for a simple one-line blocking HTTP call.

Except CallBuilder::exec no call will block, not even for DNS resolution as it is implemented internally to avoid blocking.

For https to work mio_httpc requires you specify one of the TLS implementations using features: native, openssl or rtls (rustls). Default build will fail on any https URI.

CallBuilder also has URL construction functions (host/pathsegm/query/sethttps/auth/https) which will take care of url-safe encoding.

mio_httpc does a minimal amount of allocation and in general works with buffers you provide and an internal pool of buffers that get reused on new calls.

Documentation

TODO/FEATURE LIST

EXAMPLES

Sync call

```rust extern crate miohttpc; use miohttpc::CallBuilder;

// One line blocking call.

let (responsemeta, body) = CallBuilder::get().timeoutms(5000).url("http://www.example.com")?.exec()?;

// With URL construction. // This way of building the URL is highly recommended as it will always result in correct // values by percent encoding any URL unsafe characters. // This calls: https://www.example.com/a/b?key1=val1 let (responsemeta, body) = CallBuilder::get() .timeoutms(5000) .https() .host("www.example.com") .pathsegm("a") .pathsegm("b") .query("key1","val1") .exec()?;

```

Basic async get

``` cargo run --example get --features "native" -- "https://edition.cnn.com"

// or cargo run --example get --features "openssl" -- "https://edition.cnn.com"

// or cargo run --example get --features "rtls" -- "https://edition.cnn.com" ```

```rust extern crate mio_httpc; extern crate mio;

use mio_httpc::{CallBuilder,Httpc}; use mio::{Poll,Events};

fn main() { let poll = Poll::new().unwrap(); let mut htp = Httpc::new(10,None); let args: Vec = ::std::env::args().collect(); let mut call = CallBuilder::get() .url(args[1].asstr()).expect("Can not parse url") .timeoutms(500) .call_simple(&mut htp, &poll) .expect("Call start failed");

let to = ::std::time::Duration::from_millis(100);
let mut events = Events::with_capacity(8);
'outer: loop {
    poll.poll(&mut events, Some(to)).unwrap();
    for cref in htp.timeout().into_iter() {
        if call.is_ref(cref) {
            println!("Request timed out");
            call.abort(&mut htp);
            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"

```rust extern crate mio_httpc; extern crate mio;

use mio_httpc::{CallBuilder,Httpc,WebSocket,WSPacket}; use mio::{Poll,Events}; // ws://demos.kaazing.com/echo

fn main() { let poll = Poll::new().unwrap(); let mut htp = Httpc::new(10,None); let args: Vec = ::std::env::args().collect();

let mut ws = CallBuilder::get()
    .url(args[1].as_str()).expect("Can not parse url")
    .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 {
        // ws.ping(None);
        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() {
                loop {
                    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 => {
                            break;
                        }
                        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);
                }
            }
        }
    }
    // Any ping/pong/close/send_text/send_bin has just been buffered.
    // perform and recv_packet actually send over socket.
    ws.perform(&mut htp, &poll).expect("Call failed");
}
ws.perform(&mut htp, &poll);
ws.finish(&mut htp);

} ```