use crate::*;
impl std::error::Error for ResponseError {}
impl From<std::io::Error> for ResponseError {
#[inline(always)]
fn from(error: std::io::Error) -> Self {
ResponseError::Send(error.to_string())
}
}
impl Display for ResponseError {
#[inline(always)]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotFoundStream => {
write!(f, "Not found stream")
}
Self::ConnectionClosed => {
write!(f, "Connection has been closed")
}
Self::Terminated => {
write!(f, "Current processing has been terminated")
}
Self::Send(error) => write!(f, "Send error{COLON_SPACE}{error}"),
Self::FlushError(error) => write!(f, "Flush error{COLON_SPACE}{error}"),
Self::Unknown => write!(f, "Unknown error"),
}
}
}
impl Default for Response {
#[inline(always)]
fn default() -> Self {
let http_status: HttpStatus = HttpStatus::default();
Self {
version: HttpVersion::Http1_1,
status_code: http_status.code(),
reason_phrase: http_status.to_string(),
headers: hash_map_xx_hash3_64(),
body: Vec::new(),
}
}
}
impl Response {
#[inline(always)]
fn push_header(response_string: &mut String, key: &str, value: &str) {
response_string.push_str(key);
response_string.push_str(COLON);
response_string.push_str(value);
response_string.push_str(HTTP_BR);
}
#[inline(always)]
fn push_http_first_line(&self, response_string: &mut String) {
response_string.push_str(&self.get_version().to_string());
response_string.push_str(SPACE);
response_string.push_str(&self.get_status_code().to_string());
response_string.push_str(SPACE);
response_string.push_str(self.get_reason_phrase());
response_string.push_str(HTTP_BR);
}
#[inline(always)]
pub fn try_get_header<K>(&self, key: K) -> Option<ResponseHeadersValue>
where
K: AsRef<str>,
{
self.headers.get(key.as_ref()).cloned()
}
#[inline(always)]
pub fn get_header<K>(&self, key: K) -> ResponseHeadersValue
where
K: AsRef<str>,
{
self.try_get_header(key).unwrap()
}
#[inline(always)]
pub fn try_get_header_front<K>(&self, key: K) -> Option<ResponseHeadersValueItem>
where
K: AsRef<str>,
{
self.headers
.get(key.as_ref())
.and_then(|values| values.front().cloned())
}
#[inline(always)]
pub fn get_header_front<K>(&self, key: K) -> ResponseHeadersValueItem
where
K: AsRef<str>,
{
self.try_get_header_front(key).unwrap()
}
#[inline(always)]
pub fn try_get_header_back<K>(&self, key: K) -> Option<ResponseHeadersValueItem>
where
K: AsRef<str>,
{
self.headers
.get(key.as_ref())
.and_then(|values| values.back().cloned())
}
#[inline(always)]
pub fn get_header_back<K>(&self, key: K) -> ResponseHeadersValueItem
where
K: AsRef<str>,
{
self.try_get_header_back(key).unwrap()
}
#[inline(always)]
pub fn has_header<K>(&self, key: K) -> bool
where
K: AsRef<str>,
{
self.headers.contains_key(key.as_ref())
}
#[inline(always)]
pub fn has_header_value<K, V>(&self, key: K, value: V) -> bool
where
K: AsRef<str>,
V: AsRef<str>,
{
if let Some(values) = self.headers.get(key.as_ref()) {
values.contains(&value.as_ref().to_owned())
} else {
false
}
}
#[inline(always)]
pub fn get_headers_size(&self) -> usize {
self.headers.len()
}
#[inline(always)]
pub fn try_get_header_size<K>(&self, key: K) -> Option<usize>
where
K: AsRef<str>,
{
self.headers.get(key.as_ref()).map(|values| values.len())
}
#[inline(always)]
pub fn get_header_size<K>(&self, key: K) -> usize
where
K: AsRef<str>,
{
self.try_get_header_size(key).unwrap()
}
#[inline(always)]
pub fn get_headers_values_size(&self) -> usize {
self.headers.values().map(|values| values.len()).sum()
}
#[inline(always)]
pub fn get_body_string(&self) -> String {
String::from_utf8_lossy(self.get_body()).into_owned()
}
pub fn try_get_body_json<T>(&self) -> Result<T, serde_json::Error>
where
T: DeserializeOwned,
{
serde_json::from_slice(self.get_body())
}
pub fn get_body_json<T>(&self) -> T
where
T: DeserializeOwned,
{
self.try_get_body_json().unwrap()
}
#[inline(always)]
fn should_skip_header(&self, key: &ResponseHeadersKey) -> bool {
key.trim().is_empty() || key == CONTENT_LENGTH
}
#[inline(always)]
fn set_header_without_check<K, V>(&mut self, key: K, value: V) -> &mut Self
where
K: AsRef<str>,
V: AsRef<str>,
{
let mut deque: VecDeque<String> = VecDeque::with_capacity(1);
deque.push_back(value.as_ref().to_owned());
self.headers.insert(key.as_ref().to_owned(), deque);
self
}
#[inline(always)]
pub fn set_header<K, V>(&mut self, key: K, value: V) -> &mut Self
where
K: AsRef<str>,
V: AsRef<str>,
{
let key: ResponseHeadersKey = key.as_ref().to_owned();
if self.should_skip_header(&key) {
return self;
}
let mut deque: VecDeque<String> = VecDeque::with_capacity(1);
deque.push_back(value.as_ref().to_owned());
self.headers.insert(key, deque);
self
}
#[inline(always)]
pub fn add_header<K, V>(&mut self, key: K, value: V) -> &mut Self
where
K: AsRef<str>,
V: AsRef<str>,
{
let key: ResponseHeadersKey = key.as_ref().to_owned();
if self.should_skip_header(&key) {
return self;
}
self.headers
.entry(key)
.or_default()
.push_back(value.as_ref().to_owned());
self
}
#[inline(always)]
pub fn remove_header<K>(&mut self, key: K) -> &mut Self
where
K: AsRef<str>,
{
let _ = self.headers.remove(key.as_ref()).is_some();
self
}
#[inline(always)]
pub fn remove_header_value<K, V>(&mut self, key: K, value: V) -> &mut Self
where
K: AsRef<str>,
V: AsRef<str>,
{
let key: ResponseHeadersKey = key.as_ref().to_owned();
if let Some(values) = self.headers.get_mut(&key) {
values.retain(|v| v != &value.as_ref().to_owned());
if values.is_empty() {
self.headers.remove(&key);
}
}
self
}
#[inline(always)]
pub fn clear_headers(&mut self) -> &mut Self {
self.headers.clear();
self
}
#[inline(always)]
pub fn try_get_cookies(&self) -> Option<Cookies> {
self.try_get_header_back(SET_COOKIE)
.map(|cookie_header: String| Cookie::parse(cookie_header))
}
#[inline(always)]
pub fn get_cookies(&self) -> Cookies {
self.try_get_cookies().unwrap()
}
#[inline(always)]
pub fn try_get_cookie<K>(&self, key: K) -> Option<CookieValue>
where
K: AsRef<str>,
{
self.try_get_cookies()
.and_then(|cookies: Cookies| cookies.get(key.as_ref()).cloned())
}
#[inline(always)]
pub fn get_cookie<K>(&self, key: K) -> CookieValue
where
K: AsRef<str>,
{
self.try_get_cookie(key).unwrap()
}
pub fn build(&mut self) -> ResponseData {
if self.reason_phrase.is_empty() {
self.set_reason_phrase(HttpStatus::phrase(self.get_status_code()));
}
let mut response_string: String = String::with_capacity(DEFAULT_BUFFER_SIZE);
self.push_http_first_line(&mut response_string);
let compress_type_opt: Option<Compress> = self
.try_get_header_back(CONTENT_ENCODING)
.map(|value| value.parse::<Compress>().unwrap_or_default());
if self.try_get_header_back(CONNECTION).is_none() {
self.set_header_without_check(CONNECTION, KEEP_ALIVE);
}
let content_type: ResponseHeadersValueItem =
self.try_get_header_back(CONTENT_TYPE).unwrap_or_else(|| {
let mut content_type: String = String::with_capacity(
TEXT_HTML.len() + SEMICOLON_SPACE.len() + CHARSET_UTF_8.len(),
);
content_type.push_str(TEXT_HTML);
content_type.push_str(SEMICOLON_SPACE);
content_type.push_str(CHARSET_UTF_8);
self.set_header_without_check(CONTENT_TYPE, &content_type);
content_type
});
let mut body: ResponseBody = self.get_body().clone();
if let Some(compress_type) = compress_type_opt
&& !compress_type.is_unknown()
{
body = compress_type
.encode(&body, DEFAULT_BUFFER_SIZE)
.into_owned();
}
if !content_type.eq_ignore_ascii_case(TEXT_EVENT_STREAM) {
self.set_header_without_check(CONTENT_LENGTH, body.len().to_string());
}
self.get_headers().iter().for_each(|(key, values)| {
for value in values.iter() {
Self::push_header(&mut response_string, key, value);
}
});
response_string.push_str(HTTP_BR);
let mut response_bytes: Vec<u8> = response_string.into_bytes();
response_bytes.extend_from_slice(&body);
response_bytes
}
}