hooks.lmjtfy.fun: a Cloudflare Worker that serves one page saying what jevhooks is.
The parts every Jev site's Worker repeats are Aldebaran's (third-party/rustcrates): the
address gate, the security headers, the request log, the responses, the embedded files. The
look is jev-ui's. What is here is the routing, and in content and view, the page.
7use aldebaran_axum::{bundle_or_not_found, not_found, respond}; 8use aldebaran_gate::{Canonical, Status, Unrepeatable}; 9use aldebaran_headers::Policy; 10use axum::Router; 11use axum::body::Body; 12use axum::extract::State; 13use axum::http::Response; 14use axum::routing::get; 15use jev_ui::preview::Origin; 16use tower_service::Service; 17use worker::{Context, Env, HttpRequest, event};
The static assets binding (wrangler.toml): the link preview's card, which is built, not embedded.
31const ASSETS: &str = "ASSETS";
How long a browser may keep the page before asking again.
34const PAGE_MAX_AGE_SECONDS: u32 = 300;
What a browser may load on this site: its own files and nothing else. No script runs inline
and none is evaluated (the page has no Datastar); styles may be inline because the shell puts
the site's own sheet in the head; and an image may be a data: address, because the shared
script draws the page's dotted background into one (ui.js sets --dither-paper and
--dither-pink). Without that last allowance the page loads and the dots are simply not there.
45#[derive(Clone)] 46struct App { 47 origin: Origin, 48} 49 50#[event(fetch)] 51async fn fetch(request: HttpRequest, env: Env, _context: Context) -> worker::Result<Response<Body>> { 52 let started = worker::Date::now().as_millis(); 53 let route = log::Route::of(request.uri().path()); 54 let method = log::Method::parse(request.method().as_str()); 55 let origin = origin(&env); 56 let mut response = match gate(&request, &origin) { 57 Some(answer) => answer, 58 None if route == log::Route::Card => card(request, &env).await?, 59 None => router(App { origin }).call(request).await?, 60 }; 61 62 aldebaran_axum::secure(response.headers_mut(), &policy()); 63 aldebaran_worker::write(&log::Served { 64 route, 65 method, 66 status: response.status().as_u16(), 67 millis: worker::Date::now().as_millis().saturating_sub(started), 68 }); 69 Ok(response) 70}
Any address but the canonical one (the account's workers.dev name) sends a reader on to it,
so link previews and old links move. Local addresses are answered where they are.
74fn gate(request: &HttpRequest, origin: &Origin) -> Option<Response<Body>> { 75 let canonical = Canonical::every_other_leads_to(origin.as_str()).ok()?; 76 let asked = aldebaran_axum::asked(request.method(), request.headers(), request.uri()); 77 aldebaran_axum::gated(canonical.gate(&asked, Status::PermanentRedirect, Unrepeatable::Refuse)) 78}
The link preview's card, from the static assets. Routed through the Worker so the gate and the headers apply to it like everything else.
88fn router(app: App) -> Router { 89 Router::new() 90 .route("/", get(page)) 91 .route("/favicon.svg", get(favicon)) 92 .route("/robots.txt", get(robots)) 93 .fallback(file_or_not_found) 94 .with_state(app) 95} 96 97fn origin(env: &Env) -> Origin { 98 let wanted = aldebaran_worker::var(env, "SITE_ORIGIN").unwrap_or_else(|| SITE_ORIGIN.to_owned()); 99 Origin::parse(&wanted).unwrap_or_else(|why| { 100 aldebaran_worker::failure(&format!("SITE_ORIGIN is not usable, so the default is used: {why}")); 101 Origin::parse(SITE_ORIGIN).expect("the default origin is valid (the_default_origin_is_valid)") 102 }) 103} 104 105async fn page(State(app): State<App>) -> Response<Body> { 106 aldebaran_axum::html(view::page(&app.origin).into_string(), PAGE_MAX_AGE_SECONDS) 107}
The site's own pictures, then the shared look's files, then nothing.
110async fn file_or_not_found(uri: axum::http::Uri) -> Response<Body> { 111 if FILES.find(uri.path()).is_some() { 112 return bundle_or_not_found(&FILES, &uri, NOTHING_HERE); 113 } 114 match jev_ui::asset::find(uri.path()) { 115 Some(asset) => respond(asset.content_type, asset.cache_control(uri.query()), asset.body), 116 None => not_found(NOTHING_HERE), 117 } 118}
120async fn favicon() -> Response<Body> { 121 respond("image/svg+xml", "public, max-age=86400", view::favicon()) 122} 123 124async fn robots() -> Response<Body> { 125 respond("text/plain; charset=utf-8", "public, max-age=3600", ROBOTS) 126} 127 128#[cfg(test)] 129mod tests { 130 use super::*; 131 use crate::content::CARD_PATH; 132 use axum::http::{Method, StatusCode, header}; 133 134 const CANON: &str = "https://hooks.lmjtfy.fun"; 135 136 fn request(host: &str, method: Method, target: &str) -> HttpRequest { 137 axum::http::Request::builder().method(method).uri(format!("https://{host}{target}")).header(header::HOST, host).body(worker::Body::empty()).unwrap() 138 } 139 140 fn canonical() -> Origin { 141 Origin::parse(CANON).unwrap() 142 }
A link to the account's workers.dev address still works, and lands on the real one with its path, carrying the same headers every response has.
146 #[test] 147 fn another_address_is_sent_on_to_the_canonical_one() { 148 let mut response = gate(&request("jevhooks.example.workers.dev", Method::GET, "/shots/band.svg?v=1"), &canonical()).expect("sent on"); 149 aldebaran_axum::secure(response.headers_mut(), &policy()); 150 assert_eq!(response.status(), StatusCode::PERMANENT_REDIRECT); 151 assert_eq!(response.headers()[header::LOCATION], format!("{CANON}/shots/band.svg?v=1")); 152 assert_eq!(response.headers()[header::CONTENT_SECURITY_POLICY], policy().csp().as_str()); 153 assert!(response.headers().get(header::SET_COOKIE).is_none()); 154 }
The site itself, and a developer's machine, are answered where they are.
157 #[test] 158 fn the_canonical_and_local_hosts_are_answered_here() { 159 for host in ["hooks.lmjtfy.fun", "localhost:8790", "127.0.0.1:8790"] { 160 for target in ["/", CARD_PATH, "/robots.txt"] { 161 assert!(gate(&request(host, Method::GET, target), &canonical()).is_none(), "{host}{target}"); 162 } 163 } 164 }
The page runs no script of its own and loads nothing from anywhere else; the policy says so in full, so a change to it is a change someone made on purpose.
168 #[test] 169 fn the_policy_allows_the_sites_own_files_and_nothing_else() { 170 let csp = policy().csp(); 171 assert!(csp.starts_with("default-src 'none'"), "{csp}"); 172 assert!(csp.contains("script-src 'self'"), "{csp}"); 173 // The dotted background is a picture the shared script draws and hands over as data. 174 assert!(csp.contains("img-src 'self' data:"), "{csp}"); 175 assert!(!csp.contains("unsafe-eval") && !csp.contains("http"), "{csp}"); 176 }