@@ -14,17 +14,45 @@ use base64::{engine::general_purpose::STANDARD as BASE64, Engine as _};
1414use std:: collections:: HashMap ;
1515use std:: str:: FromStr ;
1616
17- use crate :: http:: AppState ;
17+ use crate :: http:: { AppState , TlsConnectInfo } ;
1818use crate :: ip2country:: lookup_country;
1919use crate :: models:: { Header , HttpRequestLog , Response as ResponseModel } ;
2020use crate :: utils:: {
2121 config:: CONFIG , generate_request_id, get_current_timestamp, get_file_path_from_url,
22- get_subdomain_from_hostname, get_subdomain_from_path,
22+ get_subdomain_from_hostname, get_subdomain_from_path, is_private_ip ,
2323} ;
2424use serde_json:: json;
2525
2626/// Health check endpoint for monitoring and orchestration
27- pub async fn health ( State ( state) : State < AppState > ) -> impl IntoResponse {
27+ /// Only accessible from private IPs (10.x.x.x, 172.16-31.x.x, 192.168.x.x, 127.x.x.x)
28+ /// For external requests, behaves like any other route (logs request, serves custom response)
29+ pub async fn health (
30+ State ( state) : State < AppState > ,
31+ connect_info : axum:: extract:: ConnectInfo < std:: net:: SocketAddr > ,
32+ tls_info : Option < axum:: Extension < TlsConnectInfo > > ,
33+ uri : Uri ,
34+ method : axum:: http:: Method ,
35+ headers : HeaderMap ,
36+ body : Bytes ,
37+ ) -> Response {
38+ let client_ip = connect_info. 0 . ip ( ) . to_string ( ) ;
39+
40+ // Only return health stats for private/internal IPs
41+ if !is_private_ip ( & client_ip) {
42+ // For external requests, treat /health as a normal route
43+ return catch_all (
44+ State ( state) ,
45+ connect_info,
46+ tls_info,
47+ uri,
48+ method,
49+ headers,
50+ body,
51+ )
52+ . await
53+ . into_response ( ) ;
54+ }
55+
2856 let stats = state. cache . stats ( ) ;
2957
3058 let memory_used_mb = stats. memory_used_bytes as f64 / 1024.0 / 1024.0 ;
@@ -44,17 +72,21 @@ pub async fn health(State(state): State<AppState>) -> impl IntoResponse {
4472 }
4573 } ) ) ,
4674 )
75+ . into_response ( )
4776}
4877
4978/// Catch-all handler that logs HTTP requests and serves files
5079pub async fn catch_all (
5180 State ( state) : State < AppState > ,
5281 connect_info : axum:: extract:: ConnectInfo < std:: net:: SocketAddr > ,
82+ tls_info : Option < axum:: Extension < TlsConnectInfo > > ,
5383 uri : Uri ,
5484 method : axum:: http:: Method ,
5585 headers : HeaderMap ,
5686 body : Bytes ,
5787) -> impl IntoResponse {
88+ // Check if request came over TLS - this is set by our server and cannot be spoofed
89+ let is_tls = tls_info. is_some ( ) ;
5890 let host = headers
5991 . get ( header:: HOST )
6092 . and_then ( |h| h. to_str ( ) . ok ( ) )
@@ -96,18 +128,13 @@ pub async fn catch_all(
96128
97129 // Extract query string and build full URL
98130 let query_string = uri. query ( ) . map ( |s| format ! ( "?{s}" ) ) ;
99- let protocol = "HTTP/1.1" . to_string ( ) ;
100-
101- // Build full URL (fragments are not sent to server in HTTP)
102- let scheme = if headers
103- . get ( "x-forwarded-proto" )
104- . and_then ( |h| h. to_str ( ) . ok ( ) )
105- . map ( |s| s == "https" )
106- . unwrap_or ( false )
107- {
108- "https"
131+
132+ // Determine scheme and protocol from actual TLS state (cannot be spoofed by clients)
133+ let scheme = if is_tls { "https" } else { "http" } ;
134+ let protocol = if is_tls {
135+ "HTTPS/1.1" . to_string ( )
109136 } else {
110- "http"
137+ "HTTP/1.1" . to_string ( )
111138 } ;
112139 let full_url = format ! (
113140 "{}://{}{}{}" ,
@@ -179,8 +206,10 @@ pub async fn catch_all(
179206
180207 let _ = state. tx . send ( message) ;
181208
182- // Extract the file path from the URL (for /r/subdomain/path routing)
183- let file_path = get_file_path_from_url ( path) ;
209+ // Extract the file path from the URL
210+ // For main domain path-based routing (/r/subdomain/path): strips /r/subdomain prefix
211+ // For true subdomain requests: keeps path as-is (so /r/folder works)
212+ let file_path = get_file_path_from_url ( path, on_main_domain) ;
184213 return serve_file ( state, subdomain, & file_path, on_main_domain) . await ;
185214 }
186215
0 commit comments