73 lines
1.7 KiB
Rust
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(())
|
|
}
|