1use crate::config::ProxyConfig;
6use crate::health::HealthChecker;
7use crate::ratelimit::{RateLimitKey, RateLimiter};
8use crate::vendored::backend::BackendAppManager;
9use crate::vendored::forwarder::ForwarderClient;
10use crate::vendored::handler::MessageHandler;
11use crate::vendored::hyper_ext::{IncomingBodyExt, ProxyBody};
12use crate::vendored::types::PathName;
13use hyper::body::Incoming;
14use hyper::server::conn::http2;
15use hyper::service::service_fn;
16use hyper::{Request, Response};
17use hyper_util::rt::{TokioExecutor, TokioIo};
18use hyper_util::server::conn::auto;
19use std::convert::Infallible;
20use std::net::SocketAddr;
21use std::sync::Arc;
22use tokio::net::TcpListener;
23use tokio::sync::RwLock;
24use tokio_util::sync::CancellationToken;
25use tracing::{debug, error, info, warn};
26
27pub struct ProxyService {
29 backend_manager: Arc<BackendAppManager>,
31 forwarder: Arc<ForwarderClient>,
33 rate_limiter: Arc<RateLimiter>,
35 config: Arc<RwLock<ProxyConfig>>,
37}
38
39impl ProxyService {
40 pub fn new(
42 config: Arc<RwLock<ProxyConfig>>,
43 health_checker: Arc<HealthChecker>,
44 rate_limiter: Arc<RateLimiter>,
45 ) -> Self {
46 let backend_manager =
47 Arc::new(BackendAppManager::new().with_health_checker(health_checker));
48 let forwarder = Arc::new(ForwarderClient::default());
49
50 Self {
51 backend_manager,
52 forwarder,
53 rate_limiter,
54 config,
55 }
56 }
57
58 pub async fn load_config(&self) {
60 let config = self.config.read().await;
61
62 for upstream in &config.upstreams {
64 self.backend_manager.register_upstream(upstream.clone());
65 }
66
67 for route in &config.routes {
69 if let Some(upstream) = config.upstreams.iter().find(|u| u.name == route.upstream) {
71 use crate::vendored::types::ServerName;
72 let host = route.match_.host.as_deref().unwrap_or("*");
73 let path = route.match_.path.as_deref().unwrap_or("/");
74 let host = ServerName::new(host);
75 let path = PathName::new(path);
76 self.backend_manager
77 .register_route(host, path, upstream.resolved_id());
78 }
79 }
80
81 info!(
82 "Loaded {} routes and {} upstreams",
83 config.routes.len(),
84 config.upstreams.len()
85 );
86 }
87
88 pub async fn serve_http(
90 self: Arc<Self>,
91 addr: SocketAddr,
92 cancel_token: CancellationToken,
93 ) -> std::io::Result<()> {
94 let listener = TcpListener::bind(addr).await?;
95 info!("HTTP proxy listening on {}", addr);
96
97 loop {
98 tokio::select! {
99 _ = cancel_token.cancelled() => {
100 info!("HTTP proxy stopped");
101 break;
102 }
103 result = listener.accept() => {
104 match result {
105 Ok((stream, client_addr)) => {
106 if let Err(e) = stream.set_nodelay(true) {
109 debug!("Could not set TCP_NODELAY on the client socket: {}", e);
110 }
111 let service = self.clone();
112 tokio::spawn(async move {
113 let service_fn = service_fn(|req| {
114 let svc = service.clone();
115 async move {
116 svc.handle_request(req, client_addr, "http").await
117 }
118 });
119
120 let mut builder = auto::Builder::new(TokioExecutor::new());
128 builder.http2().enable_connect_protocol();
129 if let Err(err) = builder
130 .serve_connection_with_upgrades(
131 TokioIo::new(stream),
132 service_fn,
133 )
134 .await
135 {
136 debug!("Connection error: {}", err);
137 }
138 });
139 }
140 Err(e) => {
141 error!("Accept error: {}", e);
142 }
143 }
144 }
145 }
146 }
147
148 Ok(())
149 }
150
151 pub async fn serve_https(
161 self: Arc<Self>,
162 addr: SocketAddr,
163 tls_config: Arc<tokio_rustls::rustls::ServerConfig>,
164 cancel_token: CancellationToken,
165 ) -> std::io::Result<()> {
166 let acceptor = tokio_rustls::TlsAcceptor::from(tls_config);
167 let listener = TcpListener::bind(addr).await?;
168 info!("HTTPS proxy listening on {} (ALPN: h2, http/1.1)", addr);
169
170 loop {
171 tokio::select! {
172 _ = cancel_token.cancelled() => {
173 info!("HTTPS proxy stopped");
174 break;
175 }
176 result = listener.accept() => {
177 match result {
178 Ok((stream, client_addr)) => {
179 if let Err(e) = stream.set_nodelay(true) {
180 debug!("Could not set TCP_NODELAY on the client socket: {}", e);
181 }
182 let service = self.clone();
183 let acceptor = acceptor.clone();
184 tokio::spawn(async move {
185 let tls_stream = match acceptor.accept(stream).await {
186 Ok(s) => s,
187 Err(e) => {
188 debug!("TLS handshake failed: {}", e);
189 return;
190 }
191 };
192
193 let is_h2 = tls_stream
194 .get_ref()
195 .1
196 .alpn_protocol()
197 .map(|p| p == b"h2")
198 .unwrap_or(false);
199
200 let service_fn = service_fn(|req| {
201 let svc = service.clone();
202 async move {
203 svc.handle_request(req, client_addr, "https").await
204 }
205 });
206
207 let io = TokioIo::new(tls_stream);
208 let result = if is_h2 {
209 let mut builder = http2::Builder::new(TokioExecutor::new());
210 builder.enable_connect_protocol();
211 builder
212 .serve_connection(io, service_fn)
213 .await
214 .map_err(|e| {
215 Box::<dyn std::error::Error + Send + Sync>::from(
216 e.to_string(),
217 )
218 })
219 } else {
220 let mut builder = auto::Builder::new(TokioExecutor::new());
224 builder.http2().enable_connect_protocol();
225 builder
226 .serve_connection_with_upgrades(io, service_fn)
227 .await
228 .map_err(|e| {
229 Box::<dyn std::error::Error + Send + Sync>::from(
230 e.to_string(),
231 )
232 })
233 };
234
235 if let Err(err) = result {
236 debug!("HTTPS connection error: {}", err);
237 }
238 });
239 }
240 Err(e) => {
241 error!("Accept error: {}", e);
242 }
243 }
244 }
245 }
246 }
247
248 Ok(())
249 }
250
251 pub async fn serve_h2c(
262 self: Arc<Self>,
263 addr: SocketAddr,
264 cancel_token: CancellationToken,
265 ) -> std::io::Result<()> {
266 let listener = TcpListener::bind(addr).await?;
267 info!("HTTP/2-only proxy listening on {}", addr);
268
269 loop {
270 tokio::select! {
271 _ = cancel_token.cancelled() => {
272 info!("HTTP/2-only proxy stopped");
273 break;
274 }
275 result = listener.accept() => {
276 match result {
277 Ok((stream, client_addr)) => {
278 if let Err(e) = stream.set_nodelay(true) {
279 debug!("Could not set TCP_NODELAY on the client socket: {}", e);
280 }
281 let service = self.clone();
282 tokio::spawn(async move {
283 let service_fn = service_fn(|req| {
284 let svc = service.clone();
285 async move {
286 svc.handle_request(req, client_addr, "http").await
287 }
288 });
289
290 let mut builder = http2::Builder::new(TokioExecutor::new());
291 builder.enable_connect_protocol();
292 if let Err(err) = builder
293 .serve_connection(TokioIo::new(stream), service_fn)
294 .await
295 {
296 debug!("HTTP/2 connection error: {}", err);
297 }
298 });
299 }
300 Err(e) => {
301 error!("Accept error: {}", e);
302 }
303 }
304 }
305 }
306 }
307
308 Ok(())
309 }
310
311 async fn handle_request(
313 &self,
314 request: Request<Incoming>,
315 client_addr: SocketAddr,
316 proto: &str,
317 ) -> Result<Response<ProxyBody>, Infallible> {
318 let uri = request.uri().clone();
319 let method = request.method().clone();
320
321 let host = request
323 .headers()
324 .get(hyper::header::HOST)
325 .and_then(|h| h.to_str().ok())
326 .map(|h| h.split(':').next().unwrap_or(h))
327 .unwrap_or("");
328
329 let path = uri.path();
330
331 debug!("{} {} {} from {}", method, host, path, client_addr);
332
333 let (route, upstream_id) = {
335 let config = self.config.read().await;
336 let matched = config
337 .routes
338 .iter()
339 .filter(|r| r.enabled)
340 .filter(|r| {
341 let route_host = r.match_.host.as_deref().unwrap_or("*");
342 route_host == "*" || route_host == host
343 })
344 .filter(|r| {
345 let route_path = r.match_.path.as_deref().unwrap_or("/");
346 path.starts_with(route_path)
347 })
348 .max_by_key(|r| {
349 let path_len = r.match_.path.as_ref().map(|p| p.len()).unwrap_or(0);
350 (r.priority, path_len)
351 })
352 .cloned();
353
354 match matched {
355 Some(r) => {
356 let upstream_id = config
358 .upstreams
359 .iter()
360 .find(|u| u.name == r.upstream)
361 .map(|u| u.resolved_id());
362 (Some(r), upstream_id)
363 }
364 None => (None, None),
365 }
366 };
367
368 let route = match route {
369 Some(r) => r,
370 None => {
371 debug!("No route found for {} {}", host, path);
372 return Ok(MessageHandler::not_found());
373 }
374 };
375
376 let upstream_id = match upstream_id {
377 Some(id) => id,
378 None => {
379 warn!(
380 "Upstream '{}' not found for route {}",
381 route.upstream, route.name
382 );
383 return Ok(MessageHandler::service_unavailable("Upstream not found"));
384 }
385 };
386
387 if let Some(ref rate_limit) = route.rate_limit {
389 let key = RateLimitKey::Ip(client_addr.ip());
390 let rps = rate_limit
392 .requests
393 .checked_div(rate_limit.window_secs)
394 .unwrap_or(rate_limit.requests);
395 if !self
396 .rate_limiter
397 .check_with_config(key, rps, rate_limit.requests)
398 {
399 return Ok(MessageHandler::too_many_requests());
400 }
401 }
402
403 let backend = match self.backend_manager.select_backend(upstream_id, None) {
405 Some(b) => b,
406 None => {
407 warn!("No healthy backends for route {}", route.name);
408 return Ok(MessageHandler::service_unavailable(
409 "No healthy backends available",
410 ));
411 }
412 };
413
414 let (parts, body) = request.into_parts();
416 let mut forwarded_request = Request::from_parts(parts, body.boxed_body());
417
418 if MessageHandler::has_ambiguous_framing(&forwarded_request) {
421 warn!("Rejecting request with both Content-Length and Transfer-Encoding");
422 return Ok(MessageHandler::bad_request(
423 "Both Content-Length and Transfer-Encoding present",
424 ));
425 }
426
427 let upgrade_protocol = MessageHandler::upgrade_protocol(&forwarded_request);
430 let h2_protocol = MessageHandler::h2_connect_protocol(&forwarded_request);
433
434 MessageHandler::strip_hop_by_hop_headers(&mut forwarded_request);
437
438 MessageHandler::add_forwarding_headers(&mut forwarded_request, client_addr, proto);
440
441 if route.strip_path {
443 if let Some(ref prefix) = route.match_.path {
444 MessageHandler::strip_path_prefix(&mut forwarded_request, prefix);
445 }
446 }
447
448 MessageHandler::apply_route_headers(&mut forwarded_request, &route);
450
451 MessageHandler::rewrite_host_header(&mut forwarded_request, &backend.address);
453
454 if let Some(protocol) = h2_protocol {
456 debug!(
457 "Extended CONNECT to {} via {} (RFC 8441)",
458 protocol, backend.address
459 );
460 return match self
461 .forwarder
462 .forward_h2_websocket(&backend, forwarded_request, &protocol)
463 .await
464 {
465 Ok(response) => Ok(response),
466 Err(e) => {
467 error!("Extended CONNECT error to {}: {}", backend.address, e);
468 Ok(MessageHandler::bad_gateway(&format!(
469 "Extended CONNECT error: {}",
470 e
471 )))
472 }
473 };
474 }
475
476 if let Some(protocol) = upgrade_protocol {
478 MessageHandler::restore_upgrade_headers(&mut forwarded_request, &protocol);
479 debug!(
480 "Upgrading connection to {} via {}",
481 protocol, backend.address
482 );
483 return match self
484 .forwarder
485 .forward_upgrade(&backend, forwarded_request)
486 .await
487 {
488 Ok(response) => Ok(response),
489 Err(e) => {
490 error!("Upgrade error to {}: {}", backend.address, e);
491 Ok(MessageHandler::bad_gateway(&format!(
492 "Upgrade error: {}",
493 e
494 )))
495 }
496 };
497 }
498
499 match self.forwarder.forward(&backend, forwarded_request).await {
501 Ok(response) => {
502 let (parts, body) = response.into_parts();
503 Ok(Response::from_parts(parts, body.boxed_body()))
504 }
505 Err(e) => {
506 error!("Forward error to {}: {}", backend.address, e);
507 Ok(MessageHandler::bad_gateway(&format!(
508 "Backend error: {}",
509 e
510 )))
511 }
512 }
513 }
514}