use std::sync::Arc;
use std::fmt::Debug;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_json::Value;
use warp::{reject::Rejection, reply::Reply};
use warp::hyper::Uri;
use warp::http::Response;
use crate::router::HttpMethod;
use crate::router::RestRouterFunction;
pub type Result<T> = std::result::Result<T, Rejection>;
pub trait RedirectHandler<Value>: Send + Sync
where
Value: Serialize + DeserializeOwned + Send + Sync,
{
fn handle(&self, data: Value) -> anyhow::Result<String>;
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct RedirectQuery {
pub path: String,
pub connection_id: String,
pub size: Option<String>,
}
pub struct Handler;
impl Handler {
pub async fn post<R>(path: String, data: Value, auth_token: Option<String>, connection_id: Option<String>, ip_address: Option<String>, router: Arc<R>) -> Result<impl warp::Reply>
where
R: RestRouterFunction,
{
match router.route(HttpMethod::POST, path, data, auth_token, connection_id, ip_address).await {
Ok(response) => {
let status = &response.status.to_warp_status_code();
let json = warp::reply::json(&response);
Ok(warp::reply::with_status(json, status.clone()))
}
Err(e) => {
let status = &e.status.to_warp_status_code();
let json = warp::reply::json(&e);
Ok(warp::reply::with_status(json, status.clone()))
}
}
}
pub async fn get<R>(path: String, data: Value, auth_token: Option<String>, connection_id: Option<String>, ip_address: Option<String>, router: Arc<R>) -> Result<impl warp::Reply>
where
R: RestRouterFunction,
{
match router.route(HttpMethod::GET, path, data, auth_token, connection_id, ip_address).await {
Ok(response) => {
let status = &response.status.to_warp_status_code();
let json = warp::reply::json(&response);
Ok(warp::reply::with_status(json, status.clone()))
}
Err(e) => {
let status = &e.status.to_warp_status_code();
let json = warp::reply::json(&e);
Ok(warp::reply::with_status(json, status.clone()))
}
}
}
pub async fn put<R>(path: String, data: Value, auth_token: Option<String>, connection_id: Option<String>, ip_address: Option<String>, router: Arc<R>) -> Result<impl warp::Reply>
where
R: RestRouterFunction,
{
match router.route(HttpMethod::PUT, path, data, auth_token, connection_id, ip_address).await {
Ok(response) => {
let status = &response.status.to_warp_status_code();
let json = warp::reply::json(&response);
Ok(warp::reply::with_status(json, status.clone()))
}
Err(e) => {
let status = &e.status.to_warp_status_code();
let json = warp::reply::json(&e);
Ok(warp::reply::with_status(json, status.clone()))
}
}
}
pub async fn delete<R>(path: String, data: Value, auth_token: Option<String>, connection_id: Option<String>, ip_address: Option<String>, router: Arc<R>) -> Result<impl warp::Reply>
where
R: RestRouterFunction,
{
match router.route(HttpMethod::DELETE, path, data, auth_token, connection_id, ip_address).await {
Ok(response) => {
let status = &response.status.to_warp_status_code();
let json = warp::reply::json(&response);
Ok(warp::reply::with_status(json, status.clone()))
}
Err(e) => {
let status = &e.status.to_warp_status_code();
let json = warp::reply::json(&e);
Ok(warp::reply::with_status(json, status.clone()))
}
}
}
pub async fn get_binary<R>(path: String, data: Value, auth_token: Option<String>, connection_id: Option<String>, ip_address: Option<String>, router: Arc<R>) -> Result<impl warp::Reply>
where
R: RestRouterFunction,
{
match router.route_binary(HttpMethod::GET, path, data, auth_token, connection_id, ip_address).await {
Ok(Some(binary)) => {
let response = Response::builder()
.header("content-type", binary.content_type)
.body(binary.data)
.unwrap();
Ok(response)
}
Ok(None) => {
Err(warp::reject::not_found())
}
Err(e) => {
let status = e.status.to_warp_status_code();
let body = serde_json::to_vec(&e).unwrap_or_default();
let response = Response::builder()
.status(status)
.header("content-type", "application/json")
.body(body)
.unwrap();
Ok(response)
}
}
}
pub async fn get_redirect<R>(path: String, data: Value, auth_token: Option<String>, connection_id: Option<String>, router: Arc<R>) -> Result<impl warp::Reply>
where
R: RestRouterFunction,
{
println!("File router. path: {}", path);
println!("File HANDLER, data: {:?}", data);
let url = router.route_redirect(path, data, auth_token, connection_id).await;
println!("File HANDLER, url: {}", url);
match url.parse::<Uri>() {
Ok(uri) => Ok(warp::redirect::found(uri).into_response()),
Err(_) => Err(warp::reject::not_found())
}
}
pub async fn api_redirect<Value, H>(data: Value, handler: Arc<H>) -> Result<impl warp::Reply>
where
Value: Serialize + DeserializeOwned + Send + Sync,
H: RedirectHandler<Value>,
{
match handler.handle(data) {
Ok(html_response) => Ok(warp::reply::html(html_response)),
Err(_) => Err(warp::reject::reject()),
}
}
}