use http::{HeaderMap, Method, StatusCode, Version};
#[derive(Debug, Clone)]
pub struct RequestHead {
pub method: Method,
pub target: String,
pub headers: HeaderMap,
pub raw_headers: Option<Vec<(String, String)>>,
}
impl RequestHead {
pub fn new(method: Method, target: impl Into<String>) -> Self {
Self {
method,
target: target.into(),
headers: HeaderMap::new(),
raw_headers: None,
}
}
pub fn with_header(mut self, name: impl AsRef<str>, value: impl AsRef<str>) -> Self {
if let (Ok(name), Ok(value)) = (
http::header::HeaderName::try_from(name.as_ref()),
http::header::HeaderValue::try_from(value.as_ref()),
) {
self.headers.insert(name, value);
}
self
}
pub fn with_raw_header(mut self, name: impl Into<String>, value: impl Into<String>) -> Self {
let name_str = name.into();
let value_str = value.into();
if let (Ok(hname), Ok(hval)) = (
http::header::HeaderName::try_from(name_str.as_str()),
http::header::HeaderValue::try_from(value_str.as_str()),
) {
self.headers.append(hname, hval);
}
let raw = self.raw_headers.get_or_insert_with(Vec::new);
raw.push((name_str, value_str));
self
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BodyKind {
Empty,
Length(u64),
Chunked,
UntilClose,
}
#[derive(Debug, Clone)]
pub struct ResponseHead {
pub version: Version,
pub status: StatusCode,
pub headers: HeaderMap,
pub body: BodyKind,
}
impl ResponseHead {
pub fn status_forbids_body(status: StatusCode) -> bool {
status.is_informational()
|| status == StatusCode::NO_CONTENT
|| status == StatusCode::NOT_MODIFIED
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn request_head_writes_headers_it_was_given() {
let head = RequestHead::new(Method::POST, "/v1/chat/completions")
.with_header("content-type", "application/json")
.with_header("authorization", "Bearer secret");
assert_eq!(head.target, "/v1/chat/completions");
assert_eq!(
head.headers
.get("content-type")
.map(|v| v.to_str().unwrap()),
Some("application/json")
);
}
#[test]
fn no_body_statuses_are_recognized() {
assert!(ResponseHead::status_forbids_body(StatusCode::NO_CONTENT));
assert!(ResponseHead::status_forbids_body(StatusCode::NOT_MODIFIED));
assert!(ResponseHead::status_forbids_body(StatusCode::CONTINUE));
assert!(!ResponseHead::status_forbids_body(StatusCode::OK));
assert!(!ResponseHead::status_forbids_body(StatusCode::BAD_REQUEST));
}
}