wayver's git archive


a simple self-hosted git server
git clone https://git.wayver.dev/bile

src/http/mod.rs@71b17dd92232913d023854951d629e9876076719

raw
Date Commit Message Author Files + -
2026-02-23 16:23 move http-equiv permissions-policy meta to tower-helmet wayverd 4 22 26
...

1pub(crate) mod extractor;
2pub(crate) mod path;
3pub(crate) mod response;
4
5use std::sync::Arc;
6
7use axum::response::{IntoResponse as _, Response};
8use http::StatusCode;
9use syntect::parsing::SyntaxSet;
10
11use crate::{config::Config, error::Result, http::response::ErrorPage};
12
13#[derive(Clone)]
14pub(crate) struct BileState {
15    pub(crate) config: Arc<Config>,
16    pub(crate) syntax: Arc<SyntaxSet>,
17}
18
19impl BileState {
20    pub(crate) fn new(config: Config, syntax: SyntaxSet) -> Self {
21        Self {
22            config: Arc::new(config),
23            syntax: Arc::new(syntax),
24        }
25    }
26
27    pub(crate) async fn spawn<F>(&self, f: F) -> Response
28    where
29        F: FnOnce(Self) -> Result<Response> + Send + 'static,
30    {
31        let span = tracing::Span::current();
32
33        let this = self.clone();
34
35        spawn_blocking(move || span.in_scope(|| wrap_err(this.clone(), f(this)))).await
36    }
37}
38
39// TODO: https://github.com/rust-lang/rust/issues/110011
40// #[track_caller]
41async fn spawn_blocking<F, R>(f: F) -> R
42where
43    F: FnOnce() -> R + Send + 'static,
44    R: Send + 'static,
45{
46    tokio::task::spawn_blocking(f)
47        .await
48        .expect("failed to join spawn_blocking call, this should only happen due to a panic")
49}
50
51fn wrap_err(state: BileState, res: Result<Response>) -> Response {
52    match res {
53        Ok(res) => res,
54        Err(err) => {
55            tracing::error!(err=?err, "failed to handle response");
56
57            ErrorPage::from(state)
58                .with_status(StatusCode::INTERNAL_SERVER_ERROR)
59                .into_response()
60        }
61    }
62}
63
64pub(crate) struct PermissionsPolicy;
65
66impl tower_helmet::IntoHeader for PermissionsPolicy {
67    fn header_name(&self) -> http::HeaderName {
68        http::HeaderName::from_static("permissions-policy")
69    }
70
71    fn header_value(
72        &self,
73    ) -> std::result::Result<http::HeaderValue, http::header::InvalidHeaderValue> {
74        http::HeaderValue::from_str(
75            "accelerometer=(),ambient-light-sensor=(),attribution-reporting=(),autoplay=(),bluetooth=(),browsing-topics=(),camera=(),captured-surface-control=(),clipboard-read=(),clipboard-write=(),compute-pressure=(),display-capture=(),document-domain=(),encrypted-media=(),fullscreen=(),gamepad=(),geolocation=(),gyroscope=(),hid=(),identity-credentials-get=(),idle-detection=(),interest-cohort=(),local-fonts=(),magnetometer=(),microphone=(),midi=(),on-device-speech-recognition=(),otp-credentials=(),payment=(),picture-in-picture=(),private-state-token-issuance=(),private-state-token-redemption=(),publickey-credentials-create=(),publickey-credentials-get=(),screen-wake-lock=(),serial=(),speaker-selection=(),storage-access=(),sync-xhr=(),usb=(),web-share=(),window-management=(),xr-spatial-tracking=()",
76        )
77    }
78}
79