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:
parent
4f52475f2c
commit
39c31d9651
2 changed files with 34 additions and 29 deletions
|
@ -85,21 +85,25 @@ impl Client {
|
|||
stream.write_all(url_str.as_bytes()).await?;
|
||||
stream.write_all(b"\r\n").await?;
|
||||
|
||||
let status = {
|
||||
let mut buf: [u8; 3] = [0, 0, 0]; // 2 digits, space
|
||||
stream.read_exact(&mut buf).await?;
|
||||
let status = Status::parse_status(&buf)?;
|
||||
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);
|
||||
|
||||
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
|
||||
buf_reader.read_until(b'\r', &mut message).await?;
|
||||
stream.read_until(b'\r', &mut result).await?;
|
||||
// now read next char...
|
||||
buf_reader.read_exact(&mut buf).await?;
|
||||
stream.read_exact(&mut buf).await?;
|
||||
if buf[0] == b'\n' {
|
||||
// ...and check if it's LF
|
||||
break;
|
||||
|
@ -107,17 +111,18 @@ impl Client {
|
|||
// ...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());
|
||||
result.push(buf[0].into());
|
||||
}
|
||||
}
|
||||
|
||||
// trim last CR
|
||||
if message.last().is_some_and(|c| c == &b'\r') {
|
||||
message.pop();
|
||||
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)?;
|
||||
String::from_utf8(result)?
|
||||
};
|
||||
|
||||
Ok(Response::new(status, message, stream))
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Reference in a new issue