use crate::enums::http_body::HttpBody;
use crate::enums::http_error::HttpError;
use crate::enums::http_request_method::HttpRequestMethod;
use crate::enums::http_version::HttpVersion;
use crate::structures::header::header_list::HttpHeaderList;
use crate::structures::http_message::HttpMessage;
use crate::structures::http_request_builder::HttpRequestBuilder;
use crate::structures::http_stream::HttpStream;
use futures::{AsyncBufRead, AsyncWrite, AsyncWriteExt};
use log::{LogLevel, debug_lazy_with, structs::logger::Logger, trace_lazy_with};
pub struct HttpConnection<R: AsyncBufRead + Unpin, W: AsyncWrite + Unpin> {
pub stream: HttpStream<R, W>,
pub request_builder: HttpRequestBuilder,
pub logger: Logger,
}
impl<R: AsyncBufRead + Unpin, W: AsyncWrite + Unpin> HttpConnection<R, W> {
pub fn new(
stream_reader: R,
stream_writer: W,
http_version: HttpVersion,
host: &str,
request_headers: HttpHeaderList,
logger: Logger,
) -> Result<Self, HttpError> {
let stream = HttpStream::new(stream_reader, stream_writer);
let request_builder = HttpRequestBuilder::new(http_version, request_headers, host);
Ok(HttpConnection {
stream,
request_builder,
logger,
})
}
pub async fn send_request(
&mut self,
method: HttpRequestMethod,
path_query: &str,
request_headers: HttpHeaderList,
body: HttpBody,
) -> Result<usize, HttpError> {
let message = self
.request_builder
.build_request(method, path_query, request_headers, body);
match self.logger.level() {
LogLevel::Debug => debug_lazy_with!(self.logger, || "Http Request: {}{}", &self.request_builder.host, path_query),
LogLevel::Trace => trace_lazy_with!(self.logger, || "Http Request: {}\n{}", &self.request_builder.host, &message),
_ => (),
}
let bytes = message.as_bytes(true);
self.stream.writer.write_all(&bytes).await?;
self.stream.writer.flush().await?;
Ok(bytes.len())
}
pub async fn send_get_request(
&mut self,
path_query: &str,
request_headers: HttpHeaderList,
) -> Result<usize, HttpError> {
self.send_request(
HttpRequestMethod::Get,
path_query,
request_headers,
HttpBody::None,
)
.await
}
pub async fn read_response(&mut self) -> Result<HttpMessage, HttpError> {
let message = HttpMessage::read(&mut self.stream.reader).await?;
match self.logger.level() {
LogLevel::Debug => debug_lazy_with!(self.logger, || "Http Response: {}", &message.start_line),
LogLevel::Trace => trace_lazy_with!(self.logger, || "Http Response: {}", &message),
_ => (),
}
Ok(message)
}
pub fn host(&self) -> &str {
&self.request_builder.host
}
}