chadtmiller.com/knotless
git that lives in your Atmosphere account
1
10
/favicon.ico goes to the pages' icon, not a handle's profile
crates/knotless-serve/src/web/pages.rs+8−1
| @@ -37,10 +37,17 @@ static CLIENT: LazyLock<reqwest::Client> = LazyLock::new(|| { | ||
| ||
/// A router that hands every request to the app at `web`: what it answers | ||
/// compressed as this server's own answers are, brotli to a browser that | ||
/// takes it, but for what the app compressed itself, as its scripts. | ||
/// takes it, but for what the app compressed itself, as its scripts. But | ||
/// `/favicon.ico`, which crawlers and old browsers ask for whatever a page | ||
/// names, goes to the pages' icon: handed on, it would be drawn as the | ||
/// profile of a handle `favicon.ico`, looked up at every handle resolver. | ||
pub fn pages(web: String) -> Router { | ||
let web: &'static str = web.trim_end_matches('/').to_string().leak(); | ||
Router::new() | ||
.route( | ||
"/favicon.ico", | ||
axum::routing::get(|| async { axum::response::Redirect::permanent("/favicon.svg") }), | ||
) | ||
.fallback(move |req: Request| page(web, req)) | ||
.layer(tower_http::compression::CompressionLayer::new()) | ||
} | ||
crates/knotless-serve/tests/web.rs+9−0
| @@ -2853,6 +2853,15 @@ fn pages_drawn_elsewhere() { | ||
.send() | ||
.unwrap(); | ||
assert!(ours.text().unwrap().contains("keeps no index")); | ||
// Nor is `/favicon.ico`, which would be drawn as a handle's profile: it | ||
// goes to the pages' icon. | ||
let staying = Client::builder() | ||
.redirect(reqwest::redirect::Policy::none()) | ||
.build() | ||
.unwrap(); | ||
let icon = staying.get(format!("{base}/favicon.ico")).send().unwrap(); | ||
assert_eq!(icon.status().as_u16(), 308); | ||
assert_eq!(icon.headers()["location"], "/favicon.svg"); | ||
// A crawler is kept off what robots.txt keeps it off, whether it read | ||
// it or not: by the longest rule, with its escapes or without. A | ||
// browser, or a preview of a link shared, is not. | ||
docs/design/serve.md+5−0
| @@ -800,6 +800,11 @@ A crawler that calls itself a browser is not caught, and each request's | ||
log line names its client (`user_agent.original`), so they can be told | ||
apart. | ||
| ||
Crawlers and old browsers ask for `/favicon.ico` whatever a page names | ||
as its icon. Handed to the pages, it would be drawn as the profile of a | ||
handle `favicon.ico`, looked up at every handle resolver, so the server | ||
answers it with a 308 to `/favicon.svg` instead. | ||
| ||
### Who asks | ||
| ||
A query can know who asks it, as the Bluesky appview knows: an app signed | ||