httplz/examples/client.rs
2024-10-14 23:49:23 -04:00

73 lines
1.7 KiB
Rust

//! A simple client that POSTs some data to a path
//!
//! Usage:
//! cargo run --example client -- <host> <port> <path> <data>
use std::{error::Error, io::Write, net::TcpStream};
use httplz::Lift;
pub fn main() -> Result<(), Box<dyn Error>> {
let mut args = std::env::args().skip(1);
let (host, port, path, data) = args
.next()
.and_then(|h| Some((h, args.next()?, args.next()?, args.next()?)))
.ok_or_else(|| Box::<dyn Error>::from(String::from("Missing required argument")))?;
let mut stream = TcpStream::connect((host.as_str(), port.parse()?))?;
let buf = vec![0; 4096];
let mut buf = httplz_ext::Buf::new(buf);
let mut conn = httplz::Connection::new(httplz::Role::Client);
let events = &[
httplz::RequestLine {
version: httplz::Version::HTTP1_1,
method: "POST",
target: &path,
}
.into(),
httplz::HeaderOther::from(("Host", host.as_bytes())).into(),
httplz::HeaderOther::from(("Accept", "*/*")).into(),
httplz::HeaderSpecial::ContentLength(data.len()).into(),
httplz::Event::HeadersDone,
httplz::Event::BodyChunk(data.as_bytes()),
httplz::Event::SendDone,
];
for event in events {
if let Err(e) = conn.handle_send(event, &mut buf) {
panic!("{e:?}");
};
}
stream.write_all(buf.filled())?;
buf.clear();
loop {
let data = buf.filled();
let (d, r) = conn.handle_recv(data).lift();
match r {
Err(httplz::Error {
kind: httplz::ErrorKind::NeedMoreData,
..
}) => {
buf.read_from(&mut stream)?;
continue;
},
Err(e) => panic!("{e:?}"),
Ok(ev) => {
println!("{ev}");
if ev == httplz::Event::RecvDone {
break;
}
},
};
let len = buf.filled().len() - d.len();
buf.pop_front(len);
}
Ok(())
}