LE34RHBBMJT2BWLU5BHZJSHNMHQWX66QQNM2MAEDWEARCWOCSYLAC import type { HandleFetch } from '@sveltejs/kit';export const handleFetch: HandleFetch = async ({ event, request, fetch }) => {if (request.url.startsWith(import.meta.env.VITE_SERVER)) {// clone the original request, but change the URLrequest = new Request(request.url.replace(import.meta.env.VITE_SERVER, import.meta.env.VITE_LOCAL_SERVER),request);}console.log("request", request.url)const cookie = event.request.headers.get('cookie');console.log(cookie, request.headers.get('cookie'));if (cookie) {request.headers.set('cookie', cookie);}return fetch(request);};
pub struct BodyBuilder {pub http: http::response::Builder,pub html: bool,
fn cached(cache: &std::sync::RwLock<std::collections::HashMap<String, crate::config::Cached>>,t: Option<&str>,path: &str,) -> Option<axum::response::Response> {if let Ok(c) = cache.read() {if let Some(cached) = c.get(path) {debug!("cached {:?}", path);let mut resp = hyper::Response::new(cached.body.clone().into());let h = resp.headers_mut();h.insert(hyper::header::STRICT_TRANSPORT_SECURITY,HSTS.try_into().unwrap(),);if let Some(ref c) = cached.content_type {h.insert(CONTENT_TYPE, c.clone());}h.insert(hyper::header::CONTENT_LENGTH,cached.body.len().to_string().parse().unwrap(),);return Some(resp);}}None
type Body = http_body_util::Full<bytes::Bytes>;impl BodyBuilder {fn body(self, body: bytes::Bytes) -> Result<hyper::Response<Body>, http::Error> {let html =self.html|| (self.http.headers_ref().map(|m| {m.get(CONTENT_TYPE).and_then(|x| x.to_str().ok()) == Some("text/html")}) == Some(true));
let data = if html {minify_html::minify(&body, &minify_html::Cfg::default()).into()} else {body};Ok(self.http.body(data.into())?)}
#[axum::debug_handler]pub async fn node_proxy_cached(State(config): State<Config>,req: axum::extract::Request,) -> axum::response::Response {node_proxy(config, true, false, req).await.unwrap()
) -> Result<hyper::Response<Body>, axum::http::Error> {match node_proxy_(config, req).await {
) -> axum::response::Response {node_proxy(config, false, false, req).await.unwrap()}async fn node_proxy(config: Config,cache: bool,forever: bool,mut req: axum::extract::Request,) -> Result<axum::response::Response, hyper::http::Error> {let ref last_server_modif: chrono::DateTime<chrono::Utc> = config.version_time.into();if let Some(modif) = req.headers().get(http::header::IF_MODIFIED_SINCE) {debug!("req last_modif: {:?}", modif);if let Ok(parsed) = chrono::NaiveDateTime::parse_from_str(std::str::from_utf8(modif.as_bytes()).unwrap_or(""),crate::config::RFC1123,) {let parsed = parsed.and_local_timezone(chrono::Utc).unwrap();debug!("parsed: {:?} {:?}", parsed, last_server_modif);if &parsed >= last_server_modif {return Ok(http::StatusCode::NOT_MODIFIED.into_response());}}}let mut path = if cache {let path = req.uri().path();if let Some(mut r) = cached(&config.cache, None, &path) {let ref l = config.version_time_str;debug!("cached {:?}", l);let h = r.headers_mut();h.insert(hyper::header::LAST_MODIFIED, l.parse().unwrap());h.insert(hyper::header::CACHE_CONTROL,if forever {"public, max-age=31536000".parse().unwrap()} else {"public".parse().unwrap()},);h.remove(hyper::header::VARY);return Ok(r);}Some(path.to_string())} else {None};req.headers_mut().remove(ACCEPT_ENCODING);debug!("node_proxy {:?}", path);for h in req.headers() {debug!("{:?}", h);}match node_proxy_(&config, req).await {
if cache {let ref l = config.version_time_str;debug!("cache, last_modified {:?}", l);h.insert(hyper::header::LAST_MODIFIED, l.parse().unwrap());if forever {h.insert(hyper::header::CACHE_CONTROL,"public, max-age=31536000".parse().unwrap(),);} else {h.insert(hyper::header::CACHE_CONTROL, "public".parse().unwrap());}h.remove(hyper::header::VARY);} else {debug!("not cache")}
error!("proxy error {:?}", e);let resp = http::response::Response::builder().status(http::StatusCode::INTERNAL_SERVER_ERROR).header(http::header::STRICT_TRANSPORT_SECURITY, HSTS);Ok(BodyBuilder {http: resp,html: false,}.body("".into())?)
error!("grain error {:?}", e);Ok(hyper::Response::builder().status(hyper::StatusCode::INTERNAL_SERVER_ERROR).header(hyper::header::STRICT_TRANSPORT_SECURITY, HSTS).body("".into())?)
config: &crate::config::Config,req: axum::extract::Request,) -> Result<hyper::Response<hyper::body::Incoming>, crate::Error> {
config: &Config,req: hyper::Request<axum::body::Body>,) -> Result<hyper::Response<axum::body::Body>, crate::Error> {
for (k, v) in req.headers() {req_ = req_.header(k, v)}if cfg!(debug_assertions) {req_ = req_.header(HOST, "localhost:5173");} else {req_ = req_.header(HOST, "nest.pijul.org");
for (h, v) in req.headers() {if h == HOST {req_ = req_.header(HOST, config.host.clone());} else {req_ = req_.header(h, v.clone());}
let req_ = req_.body(body)?;Ok(sender.send_request(req_).await?)
let bytes = axum::body::to_bytes(body, usize::MAX).await.unwrap();let req_: http::Request<axum::body::Body> = req_.body(bytes.into())?;debug!("node_proxy_ {:?}", req_);let mut resp = sender.send_request(req_).await?;let body = resp.body_mut().collect().await.unwrap().to_bytes();Ok(resp.map(|_| body.into()))
tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| {format!("{}=debug,tower_http=debug,axum::rejection=trace",env!("CARGO_CRATE_NAME")).into()}),
tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| "nest=debug,tower_http=debug,axum::rejection=trace".into()),
.route("/static/{*wildcard}", any(proxy::node_proxy_resp)).route("/_app/immutable/{*wildcard}", any(proxy::node_proxy_resp))
.route("/static/{*wildcard}", any(proxy::node_proxy_cached)).route("/_app/immutable/{*wildcard}", any(proxy::node_proxy_cached))
tracing::debug!("listening on {}", https_addr);let https_worker = tokio::spawn(axum_server::bind_rustls(https_addr, tls_config).serve(app.clone().into_make_service_with_connect_info::<SocketAddr>(),),);
let app_ = app.clone();let (https_worker, http_worker) = if let Some(tls_config) = tls_config {(tokio::spawn(axum_server::bind_rustls(https_addr, tls_config).serve(app.into_make_service_with_connect_info::<SocketAddr>()),),tokio::spawn(async move {redirect_http_to_https(config_file.http.http_port,config_file.http.https_port,app_,).await;Ok::<_, Error>(())}),)} else {let listener = tokio::net::TcpListener::bind(http_addr).await.unwrap();let listener2 = tokio::net::TcpListener::bind(https_addr).await.unwrap();tracing::debug!("listening on {}", listener.local_addr().unwrap());use axum::handler::HandlerWithoutStateExt;(tokio::spawn(async move {axum::serve(listener,app.into_make_service_with_connect_info::<SocketAddr>(),).await}),tokio::spawn(async move {axum::serve(listener2,app_.into_make_service_with_connect_info::<SocketAddr>(),).await?;Ok::<_, Error>(())}),)};
pub async fn make_tls() -> Result<axum_server::tls_rustls::RustlsConfig, TlsError> {let key = std::env::var("tls_key").unwrap().into_bytes();let certs = std::env::var("tls_cert").unwrap().into_bytes();Ok(axum_server::tls_rustls::RustlsConfig::from_pem(certs, key).await.unwrap())
pub async fn make_tls() -> Result<Option<axum_server::tls_rustls::RustlsConfig>, TlsError> {if let (Ok(key), Ok(cert)) = (std::env::var("tls_key"), std::env::var("tls_cert")) {Ok(Some(axum_server::tls_rustls::RustlsConfig::from_pem(cert.into_bytes(), key.into_bytes()).await.unwrap(),))} else {Ok(None)}
hostname: config_file.host.clone(),host: {let mut h = config_file.host.clone();if config_file.http.https_port != 443 {h.push_str(&format!(":{}", config_file.http.https_port));}h},
aws_ses_zone: config_file.email.region.parse().unwrap(),hostname: config_file.hostname.clone(),host: config_file.host.clone(),
"wit-bindgen",
"wit-bindgen 0.46.0",][[package]]name = "wasip3"version = "0.4.0+wasi-0.3.0-rc-2026-01-06"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5"dependencies = ["wit-bindgen 0.51.0",
][[package]]name = "wasm-encoder"version = "0.244.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319"dependencies = ["leb128fmt","wasmparser",][[package]]name = "wasm-metadata"version = "0.244.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909"dependencies = ["anyhow","indexmap","wasm-encoder","wasmparser",][[package]]name = "wasmparser"version = "0.244.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe"dependencies = ["bitflags 2.10.0","hashbrown 0.15.5","indexmap","semver",
[[package]]name = "wit-bindgen"version = "0.51.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"dependencies = ["wit-bindgen-rust-macro",][[package]]name = "wit-bindgen-core"version = "0.51.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc"dependencies = ["anyhow","heck 0.5.0","wit-parser",][[package]]name = "wit-bindgen-rust"version = "0.51.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21"dependencies = ["anyhow","heck 0.5.0","indexmap","prettyplease","syn 2.0.111","wasm-metadata","wit-bindgen-core","wit-component",][[package]]name = "wit-bindgen-rust-macro"version = "0.51.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a"dependencies = ["anyhow","prettyplease","proc-macro2","quote","syn 2.0.111","wit-bindgen-core","wit-bindgen-rust",][[package]]name = "wit-component"version = "0.244.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2"dependencies = ["anyhow","bitflags 2.10.0","indexmap","log","serde","serde_derive","serde_json","wasm-encoder","wasm-metadata","wasmparser","wit-parser",]
name = "wit-parser"version = "0.244.0"source = "registry+https://github.com/rust-lang/crates.io-index"checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736"dependencies = ["anyhow","id-arena","indexmap","log","semver","serde","serde_derive","serde_json","unicode-xid","wasmparser",][[package]]