important fix for buffered stream + code cleanup

a `TlsStream<TcpStream>` was being wrapped in a `BufReader` during header parsing,
but then the pure stream (without BufReader) was being passed into a Response constructor,
discarding all content in an internal BufReader's buffer,
resulting in an incomplete body (truncated at the beginning)
or empty at all
This commit is contained in:
DarkCat09 2024-08-06 18:33:11 +04:00
parent 4f52475f2c
commit 39c31d9651
Signed by: DarkCat09
GPG key ID: 0A26CD5B3345D6E3
2 changed files with 34 additions and 29 deletions

View file

@ -85,39 +85,44 @@ impl Client {
stream.write_all(url_str.as_bytes()).await?;
stream.write_all(b"\r\n").await?;
let mut buf: [u8; 3] = [0, 0, 0]; // 2 digits, space
stream.read_exact(&mut buf).await?;
let status = Status::parse_status(&buf)?;
let status = {
let mut buf: [u8; 3] = [0, 0, 0]; // 2 digits, space
stream.read_exact(&mut buf).await?;
Status::parse_status(&buf)?
};
let mut message: Vec<u8> = Vec::new();
let mut buf_reader = tokio::io::BufReader::new(&mut stream);
let mut buf: [u8; 1] = [0]; // buffer for LF (\n)
let mut stream = tokio::io::BufReader::new(stream);
// reading message after status code
// until CRLF (\r\n)
loop {
// until CR
buf_reader.read_until(b'\r', &mut message).await?;
// now read next char...
buf_reader.read_exact(&mut buf).await?;
if buf[0] == b'\n' {
// ...and check if it's LF
break;
} else {
// ...otherwise, CR is a part of message, not a CRLF terminator,
// so append that one byte that's supposed to be LF (but not LF)
// to the message buffer
message.push(buf[0].into());
let message = {
let mut result: Vec<u8> = Vec::new();
let mut buf = [0u8]; // buffer for LF (\n)
// reading message after status code
// until CRLF (\r\n)
loop {
// until CR
stream.read_until(b'\r', &mut result).await?;
// now read next char...
stream.read_exact(&mut buf).await?;
if buf[0] == b'\n' {
// ...and check if it's LF
break;
} else {
// ...otherwise, CR is a part of message, not a CRLF terminator,
// so append that one byte that's supposed to be LF (but not LF)
// to the message buffer
result.push(buf[0].into());
}
}
}
// trim last CR
if message.last().is_some_and(|c| c == &b'\r') {
message.pop();
}
// trim last CR
if result.last().is_some_and(|c| c == &b'\r') {
result.pop();
}
// Vec<u8> -> ASCII or UTF-8 String
let message = String::from_utf8(message)?;
// Vec<u8> -> ASCII or UTF-8 String
String::from_utf8(result)?
};
Ok(Response::new(status, message, stream))
}

View file

@ -3,7 +3,7 @@ use crate::{status::Status, LibError, ReplyType};
use bytes::Bytes;
use tokio::io::AsyncReadExt;
type BodyStream = tokio_rustls::client::TlsStream<tokio::net::TcpStream>;
type BodyStream = tokio::io::BufReader<tokio_rustls::client::TlsStream<tokio::net::TcpStream>>;
#[derive(Debug)]
pub struct Response {