chadtmiller.com/knotless
Git hosted in your atproto account, on any stock PDS, fast enough for agents.
git clone knotless://chadtmiller.com/knotlessneeds the knotless git helper. set it up
//! The pages: every request this server does not answer itself, handed to
//! the SvelteKit app that draws them, which reads back under `/_data`.
use axum::Router;
use axum::body::Body;
use axum::extract::Request;
use axum::http::{HeaderMap, HeaderValue, StatusCode, header};
use axum::response::{IntoResponse, Response};
use std::sync::LazyLock;
/// The largest request body handed on: the pages take none to speak of.
const BODY_LIMIT: usize = 1 << 20;
/// Headers about one hop of a connection, which are not handed on.
const HOP: [header::HeaderName; 6] = [
header::CONNECTION,
header::HOST,
header::TRANSFER_ENCODING,
header::CONTENT_LENGTH,
header::UPGRADE,
header::TE,
];
static CLIENT: LazyLock<reqwest::Client> = LazyLock::new(|| {
reqwest::Client::builder()
.redirect(reqwest::redirect::Policy::none())
.build()
.expect("a client builds")
});
/// A router that hands every request to the app at `web`.
pub fn pages(web: String) -> Router {
let web: &'static str = web.trim_end_matches('/').to_string().leak();
Router::new().fallback(move |req: Request| page(web, req))
}
async fn page(web: &str, req: Request) -> Response {
match handed(web, req).await {
Ok(res) => res,
Err(e) => (
StatusCode::BAD_GATEWAY,
format!("The pages are not being drawn: {e:#}"),
)
.into_response(),
}
}
/// `req`, as the app at `web` answers it. The app sees the host it was
/// asked for, as `x-forwarded-host`.
async fn handed(web: &str, req: Request) -> anyhow::Result<Response> {
let (parts, body) = req.into_parts();
let at = parts.uri.path_and_query().map_or("/", |p| p.as_str());
let mut headers = kept(&parts.headers);
if let Some(host) = parts.headers.get(header::HOST) {
headers.insert("x-forwarded-host", host.clone());
}
headers
.entry("x-forwarded-proto")
.or_insert(HeaderValue::from_static("http"));
let body = axum::body::to_bytes(body, BODY_LIMIT).await?;
let answer = CLIENT
.request(parts.method, format!("{web}{at}"))
.headers(headers)
.body(body)
.send()
.await?;
let mut res = Response::builder().status(answer.status());
let mut headers = kept(answer.headers());
for (name, value) in [
(header::X_CONTENT_TYPE_OPTIONS, "nosniff"),
(header::REFERRER_POLICY, "same-origin"),
] {
headers
.entry(name)
.or_insert(HeaderValue::from_static(value));
}
*res.headers_mut().unwrap() = headers;
Ok(res.body(Body::from(answer.bytes().await?))?)
}
/// `headers`, but for those about one hop.
fn kept(headers: &HeaderMap) -> HeaderMap {
let mut out = headers.clone();
for name in HOP {
out.remove(name);
}
out
}