simple_proxy/middlewares/
router.rs1use http::uri::{Parts, Uri};
2use hyper::header::HeaderValue;
3use hyper::{Body, Request, StatusCode};
4use regex::Regex;
5
6use crate::proxy::error::MiddlewareError;
7use crate::proxy::middleware::MiddlewareResult::Next;
8use crate::proxy::middleware::{Middleware, MiddlewareResult};
9use crate::proxy::service::{ServiceContext, State};
10
11use serde_json;
12
13#[derive(Clone)]
14pub struct Router {
15 routes: RouterRules,
16 name: String,
17}
18
19#[derive(Debug, Clone, Deserialize)]
20pub struct RouteRegex {
21 #[serde(with = "serde_regex")]
22 pub host: Regex,
23 #[serde(with = "serde_regex")]
24 pub path: Regex,
25}
26
27#[derive(Debug, Clone, Deserialize)]
28pub struct Route {
29 pub from: RouteRegex,
30 pub to: RouteRegex,
31 pub public: bool,
32}
33
34#[derive(Debug, Clone, Deserialize)]
35pub struct RouterRulesWrapper {
36 pub rules: RouterRules,
37}
38
39pub type RouterRules = Vec<Route>;
40
41#[derive(Serialize, Deserialize, Debug)]
42pub struct MatchedRoute {
43 pub uri: String,
44 pub public: bool,
45}
46
47pub trait RouterConfig {
48 fn get_router_filename(&self) -> &str;
49}
50
51fn get_host_and_path(req: &mut Request<Body>) -> Result<(String, String), MiddlewareError> {
52 let uri = req.uri();
53 let path = uri
54 .path_and_query()
55 .map(ToString::to_string)
56 .unwrap_or_else(|| String::from(""));
57
58 match uri.host() {
59 Some(host) => Ok((String::from(host), path)),
60 None => Ok((
61 String::from(req.headers().get("host").unwrap().to_str()?),
62 path,
63 )),
64 }
65}
66
67fn inject_new_uri(
68 req: &mut Request<Body>,
69 old_host: &str,
70 host: &str,
71 path: &str,
72) -> Result<(), MiddlewareError> {
73 {
74 let headers = req.headers_mut();
75
76 headers.insert("X-Forwarded-Host", HeaderValue::from_str(old_host).unwrap());
77 headers.insert("host", HeaderValue::from_str(host).unwrap());
78 }
79 let mut parts = Parts::default();
80 parts.scheme = Some("http".parse()?);
81 parts.authority = Some(host.parse()?);
82 parts.path_and_query = Some(path.parse()?);
83
84 debug!("Found a route to {:?}", parts);
85
86 *req.uri_mut() = Uri::from_parts(parts)?;
87
88 Ok(())
89}
90
91impl Middleware for Router {
92 fn name() -> String {
93 String::from("Router")
94 }
95
96 fn before_request(
97 &mut self,
98 req: &mut Request<Body>,
99 context: &ServiceContext,
100 state: &State,
101 ) -> Result<MiddlewareResult, MiddlewareError> {
102 let routes = &self.routes;
103
104 let (host, path) = get_host_and_path(req)?;
105 debug!("Routing => Host: {} Path: {}", host, path);
106
107 for route in routes {
108 let (re_host, re_path) = (&route.from.host, &route.from.path);
109 let to = &route.to;
110 let public = route.public;
111
112 debug!("Trying to convert from {} / {:?}", &re_host, &re_path);
113
114 if re_host.is_match(&host) {
115 let new_host = re_host.replace(&host, to.host.as_str());
116
117 let new_path = if re_path.is_match(&path) {
118 re_path.replace(&path, to.path.as_str())
119 } else {
120 continue;
121 };
122
123 debug!("Proxying to {}", &new_host);
124 inject_new_uri(req, &host, &new_host, &new_path)?;
125 self.set_state(
126 context.req_id,
127 state,
128 serde_json::to_string(&MatchedRoute {
129 uri: req.uri().to_string(),
130 public,
131 })?,
132 )?;
133 return Ok(Next);
134 }
135 }
136
137 Err(MiddlewareError::new(
138 String::from("No route matched"),
139 Some(String::from("Not found")),
140 StatusCode::NOT_FOUND,
141 ))
142 }
143}
144
145fn read_routes<T: RouterConfig>(config: &T) -> RouterRules {
146 use std::fs::File;
147 use std::io::prelude::Read;
148
149 let mut f = File::open(config.get_router_filename()).expect("Router config not found !");
150
151 let mut data = String::new();
152 f.read_to_string(&mut data)
153 .expect("Cannot read Router config !");
154
155 let rules: RouterRulesWrapper =
156 serde_json::from_str(&data).expect("Cannot parse Router config file !");
157
158 rules.rules
159}
160
161impl Router {
162 pub fn new<T: RouterConfig>(config: &T) -> Self {
163 Router {
164 routes: read_routes(config),
165 name: String::from("Router"),
166 }
167 }
168}