1pub use axum::response;
2pub use axum::routing;
3use axum::Router;
4pub use http::StatusCode;
5use tonic::service::Routes;
6
7pub mod extract {
8 pub use axum::extract::*;
9 pub use axum_extra::extract::Query;
10}
11
12pub trait APIHandler {
16 type State: Clone + Send + Sync + 'static;
17
18 fn generate_initial_state(&self) -> Self::State;
19 fn generate_routes(&self) -> Router<Self::State>;
20}
21
22#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
26pub enum EndpointType {
27 Unprivileged,
29
30 Privileged,
32}
33
34impl EndpointType {
35 pub fn name(&self) -> &'static str {
37 match self {
38 Self::Unprivileged => "unprivileged",
39 Self::Privileged => "privileged",
40 }
41 }
42}
43
44#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
48pub enum EndpointProtocol {
49 Http,
51
52 Grpc,
54}
55
56impl EndpointProtocol {
57 pub fn name(&self) -> &'static str {
59 match self {
60 Self::Http => "HTTP",
61 Self::Grpc => "gRPC",
62 }
63 }
64}
65
66#[derive(Clone, Debug)]
71pub struct DynamicRoute {
72 endpoint_type: EndpointType,
74
75 endpoint_protocol: EndpointProtocol,
77
78 router: Router<()>,
80}
81
82impl DynamicRoute {
83 pub fn http<T: APIHandler>(endpoint_type: EndpointType, handler: T) -> Self {
85 let router = handler.generate_routes().with_state(handler.generate_initial_state());
86 Self::new(endpoint_type, EndpointProtocol::Http, router)
87 }
88
89 pub fn grpc(endpoint_type: EndpointType, routes: Routes) -> Self {
91 let router = routes.prepare().into_axum_router();
92 Self::new(endpoint_type, EndpointProtocol::Grpc, router)
93 }
94
95 fn new(endpoint_type: EndpointType, endpoint_protocol: EndpointProtocol, router: Router<()>) -> Self {
96 Self {
97 endpoint_type,
98 endpoint_protocol,
99 router,
100 }
101 }
102
103 pub fn endpoint_type(&self) -> EndpointType {
105 self.endpoint_type
106 }
107
108 pub fn endpoint_protocol(&self) -> EndpointProtocol {
110 self.endpoint_protocol
111 }
112
113 pub fn into_router(self) -> Router<()> {
115 self.router
116 }
117}