mz_environmentd/http/
console.rs1use std::sync::Arc;
13
14use axum::Extension;
15use axum::body::Body;
16use axum::http::{Request, StatusCode};
17use axum::response::{IntoResponse, Response};
18use http::HeaderValue;
19use http::header::HOST;
20use hyper::Uri;
21use hyper_tls::HttpsConnector;
22use hyper_util::client::legacy::Client;
23use hyper_util::client::legacy::connect::HttpConnector;
24use hyper_util::rt::TokioExecutor;
25
26pub(crate) struct ConsoleProxyConfig {
27 client: Client<HttpsConnector<HttpConnector>, Body>,
29
30 url: String,
32
33 route_prefix: String,
35}
36
37impl ConsoleProxyConfig {
38 pub(crate) fn new(proxy_url: Option<String>, route_prefix: String) -> Self {
39 let mut url = proxy_url.unwrap_or_else(|| "https://console.materialize.com".to_string());
40 if let Some(new) = url.strip_suffix('/') {
41 url = new.to_string();
42 }
43 Self {
44 client: Client::builder(TokioExecutor::new()).build(HttpsConnector::new()),
45 url,
46 route_prefix,
47 }
48 }
49}
50
51pub(crate) async fn handle_internal_console(
58 console_config: Extension<Arc<ConsoleProxyConfig>>,
59 mut req: Request<Body>,
60) -> Result<Response, StatusCode> {
61 let path = req.uri().path();
62 let mut path_query = req
63 .uri()
64 .path_and_query()
65 .map(|v| v.as_str())
66 .unwrap_or(path);
67 if let Some(stripped_path_query) = path_query.strip_prefix(&console_config.route_prefix) {
68 path_query = stripped_path_query;
69 }
70
71 let uri = Uri::try_from(format!("{}{}", &console_config.url, path_query)).unwrap();
72 let host = uri.host().unwrap().to_string();
73 *req.uri_mut() = uri;
75
76 req.headers_mut()
78 .insert(HOST, HeaderValue::from_str(&host).unwrap());
79
80 Ok(console_config
82 .client
83 .request(req)
84 .await
85 .map_err(|err| {
86 tracing::warn!("Error retrieving console url: {}", err);
87 StatusCode::BAD_REQUEST
88 })?
89 .into_response())
90}