use axum::http::request::Parts;
use std::any::TypeId;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum HostType {
Http,
Rpc,
Ws,
Unknown,
}
#[derive(Clone, Debug)]
pub struct ExecutionContext {
host_type: HostType,
pub method: axum::http::Method,
pub path_and_query: String,
controller_type_id: Option<TypeId>,
controller_name: Option<&'static str>,
handler_type_id: Option<TypeId>,
handler_name: Option<&'static str>,
}
impl ExecutionContext {
pub fn from_http_parts(parts: &Parts) -> Self {
let path_and_query = parts
.uri
.path_and_query()
.map(|pq| pq.as_str().to_owned())
.unwrap_or_else(|| parts.uri.path().to_owned());
Self {
host_type: HostType::Http,
method: parts.method.clone(),
path_and_query,
controller_type_id: None,
controller_name: None,
handler_type_id: None,
handler_name: None,
}
}
pub fn with_handler_meta(
mut self,
controller_name: Option<&'static str>,
controller_type_id: Option<TypeId>,
handler_name: Option<&'static str>,
handler_type_id: Option<TypeId>,
) -> Self {
self.controller_name = controller_name;
self.controller_type_id = controller_type_id;
self.handler_name = handler_name;
self.handler_type_id = handler_type_id;
self
}
pub fn get_type(&self) -> HostType {
self.host_type
}
pub fn get_class(&self) -> Option<TypeId> {
self.controller_type_id
}
pub fn get_handler(&self) -> Option<TypeId> {
self.handler_type_id
}
pub fn get_class_name(&self) -> Option<&'static str> {
self.controller_name
}
pub fn get_handler_name(&self) -> Option<&'static str> {
self.handler_name
}
pub fn with_host_type(mut self, host_type: HostType) -> Self {
self.host_type = host_type;
self
}
pub fn trace_id(&self) -> Option<String> {
crate::current_trace_context().map(|t| t.trace_id_hex())
}
pub fn span_id(&self) -> Option<String> {
crate::current_trace_context().map(|t| t.span_id_hex())
}
pub fn trace_flags(&self) -> Option<String> {
crate::current_trace_context().map(|t| t.trace_flags_hex())
}
pub fn switch_to_http(&self) -> HttpExecutionArguments<'_> {
HttpExecutionArguments { ctx: self }
}
pub fn switch_to_rpc(&self) -> RpcExecutionArguments<'_> {
RpcExecutionArguments { ctx: self }
}
pub fn switch_to_ws(&self) -> WsExecutionArguments<'_> {
WsExecutionArguments { ctx: self }
}
}
pub struct HttpExecutionArguments<'a> {
ctx: &'a ExecutionContext,
}
impl<'a> HttpExecutionArguments<'a> {
pub fn method(&self) -> &'a axum::http::Method {
&self.ctx.method
}
pub fn path_and_query(&self) -> &'a str {
self.ctx.path_and_query.as_str()
}
}
pub struct RpcExecutionArguments<'a> {
ctx: &'a ExecutionContext,
}
impl<'a> RpcExecutionArguments<'a> {
pub fn pattern(&self) -> &'a str {
self.ctx.path_and_query.as_str()
}
pub fn handler_name(&self) -> Option<&'static str> {
self.ctx.handler_name
}
}
pub struct WsExecutionArguments<'a> {
ctx: &'a ExecutionContext,
}
impl<'a> WsExecutionArguments<'a> {
pub fn path_and_query(&self) -> &'a str {
self.ctx.path_and_query.as_str()
}
pub fn handler_name(&self) -> Option<&'static str> {
self.ctx.handler_name
}
}