httplz/examples/client.rs
2024-10-14 22:19:45 -04:00

72 lines
1.6 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 uhttp::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, port.parse()?))?;
let buf = vec![0; 4096];
let mut buf = uhttp_ext::Buf::new(buf);
let mut conn = uhttp::Connection::new(uhttp::Role::Client);
let events = &[
uhttp::Event::RequestLine(uhttp::RequestLine {
version: uhttp::Version::HTTP1_1,
method: "POST",
target: &path,
}),
uhttp::Event::Header(uhttp::Header::Special(uhttp::HeaderSpecial::ContentLength(
data.len(),
))),
uhttp::Event::HeadersDone,
uhttp::Event::BodyChunk(data.as_bytes()),
uhttp::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 {
buf.read_from(&mut stream)?;
let data = buf.filled();
let (d, r) = conn.handle_recv(data).lift();
match r {
Err(uhttp::Error {
kind: uhttp::ErrorKind::NeedMoreData,
..
}) => {
continue;
},
Err(e) => panic!("{e:?}"),
Ok(ev) => {
println!("{ev}");
if ev == uhttp::Event::RecvDone {
break;
}
},
};
let len = buf.filled().len() - d.len();
buf.pop_front(len);
}
Ok(())
}