use std::net::SocketAddr;
use std::sync::Arc;
use async_trait::async_trait;
use bytes::Bytes;
use http::{HeaderMap, Method, StatusCode};
#[derive(Debug)]
pub struct RequestParts<'a> {
pub method: &'a Method,
pub path: &'a str,
pub query: Option<&'a str>,
pub headers: &'a HeaderMap,
pub peer: SocketAddr,
}
pub enum Decision {
Allow {
inject_headers: HeaderMap,
},
Deny {
status: StatusCode,
body: Bytes,
},
Redirect {
location: String,
},
}
#[async_trait]
pub trait AuthDecider: Send + Sync {
async fn decide(&self, req: &RequestParts<'_>) -> Decision;
}
#[derive(Debug, Clone)]
pub struct MetadataDocument {
pub path: String,
pub json: serde_json::Value,
}
impl MetadataDocument {
pub fn new(path: impl Into<String>, json: serde_json::Value) -> Self {
Self {
path: path.into(),
json,
}
}
}
#[async_trait]
pub trait OidcBackend: Send + Sync {
fn metadata_documents(&self) -> Vec<MetadataDocument>;
fn jwks(&self) -> MetadataDocument;
fn userinfo_path(&self) -> String {
"/userinfo".to_string()
}
async fn userinfo(&self, bearer: &str) -> Option<serde_json::Value>;
}
#[derive(Debug)]
pub struct RouteRequest {
pub method: Method,
pub uri: http::Uri,
pub headers: HeaderMap,
pub body: Bytes,
pub peer: SocketAddr,
}
pub struct RouteResponse {
pub status: StatusCode,
pub headers: HeaderMap,
pub body: Bytes,
}
impl RouteResponse {
pub fn new(status: StatusCode, body: impl Into<Bytes>) -> Self {
Self {
status,
headers: HeaderMap::new(),
body: body.into(),
}
}
}
#[async_trait]
pub trait ExtraRouteHandler: Send + Sync {
async fn handle(&self, req: RouteRequest) -> RouteResponse;
}
#[derive(Clone)]
pub struct ExtraRoute {
pub(crate) method: Method,
pub(crate) path: String,
pub(crate) handler: Arc<dyn ExtraRouteHandler>,
}
impl ExtraRoute {
pub fn new(
method: Method,
path: impl Into<String>,
handler: Arc<dyn ExtraRouteHandler>,
) -> Self {
Self {
method,
path: path.into(),
handler,
}
}
}