use crate::auth::IClaims;
use crate::error::Result;
use std::collections::HashMap;
pub struct HttpStatus;
impl HttpStatus {
pub const OK: u16 = 200;
pub const CREATED: u16 = 201;
pub const NO_CONTENT: u16 = 204;
pub const BAD_REQUEST: u16 = 400;
pub const UNAUTHORIZED: u16 = 401;
pub const FORBIDDEN: u16 = 403;
pub const NOT_FOUND: u16 = 404;
pub const INTERNAL_SERVER_ERROR: u16 = 500;
}
pub trait IClaimsExt {
fn set_claims(&mut self, claims: Box<dyn IClaims>);
fn claims(&self) -> Option<&dyn IClaims>;
}
pub trait IHttpContext: IClaimsExt + Send {
fn request(&self) -> &dyn IHttpRequest;
fn request_mut(&mut self) -> &mut dyn IHttpRequest;
fn response(&self) -> &dyn IHttpResponse;
fn response_mut(&mut self) -> &mut dyn IHttpResponse;
}
#[async_trait::async_trait]
pub trait IHttpRequest: Send {
fn method(&self) -> &str;
fn path(&self) -> &str;
fn header(&self, name: &str) -> Option<&str>;
fn query(&self) -> &HashMap<String, String>;
fn route_params(&self) -> &HashMap<String, String>;
fn route_params_mut(&mut self) -> &mut HashMap<String, String>;
fn route_pattern(&self) -> Option<&str>;
fn route_pattern_mut(&mut self) -> &mut Option<String>;
async fn body_bytes(&self) -> Result<Vec<u8>>;
async fn body_text(&self) -> Result<String> {
let bytes = self.body_bytes().await?;
String::from_utf8(bytes).map_err(|e| crate::error::Error::Http(e.to_string()))
}
}
#[async_trait::async_trait]
pub trait IHttpResponse: Send {
fn status(&self) -> u16;
fn set_status(&mut self, code: u16);
fn set_header(&mut self, key: &str, value: &str);
fn has_body(&self) -> bool {
false
}
async fn write_bytes(&mut self, data: Vec<u8>) -> Result<()>;
async fn write_text(&mut self, text: &str) -> Result<()> {
self.write_bytes(text.as_bytes().to_vec()).await
}
}
pub async fn write_json_response<T: serde::Serialize + Send>(
resp: &mut dyn IHttpResponse,
value: &T,
) -> Result<()> {
let json = serde_json::to_vec(value)?;
resp.set_header("content-type", "application/json");
resp.write_bytes(json).await
}
pub async fn read_json_body<T: serde::de::DeserializeOwned>(req: &dyn IHttpRequest) -> Result<T> {
let bytes = req.body_bytes().await?;
serde_json::from_slice(&bytes).map_err(crate::error::Error::Serialization)
}
pub type Json<T> = T;
#[async_trait::async_trait]
pub trait FromHttpContext: Sized + Send + 'static {
async fn from_http_context(ctx: &dyn IHttpContext) -> Result<Self>;
}