summaryrefslogtreecommitdiff
path: root/src/web/http.rs
blob: 7ab1b11804b7720e4647e0da7fafcaa0a45cff6e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
use axum::{
    body::Body,
    http::{header::HeaderName, HeaderValue, Request, StatusCode},
    response::{IntoResponse, Response},
};
use std::str;
use tower::ServiceExt;
use tower_http::services::ServeFile;

pub fn text(code: u16, msg: &str) -> Response {
    (status_code(code), msg.to_owned()).into_response()
}

pub fn json(code: u16, json: &str) -> Response {
    let mut res = (status_code(code), json.to_owned()).into_response();
    res.headers_mut().insert(
        HeaderName::from_static("content-type"),
        HeaderValue::from_static("application/json"),
    );
    res
}

pub async fn serve(path: &str) -> Response {
    if !path.chars().any(|c| c == '.') {
        return text(403, "Invalid file path");
    }

    let path = format!("public{path}");
    let file = ServeFile::new(path);

    let Ok(mut res) = file.oneshot(Request::new(Body::empty())).await else {
        tracing::error!("Error while fetching file");
        return text(500, "Error when fetching file")
    };

    if res.status() != StatusCode::OK {
        return text(404, "File not found");
    }

    res.headers_mut().insert(
        HeaderName::from_static("cache-control"),
        HeaderValue::from_static("max-age=300"),
    );

    res.into_response()
}

fn status_code(code: u16) -> StatusCode {
    StatusCode::from_u16(code).map_or(StatusCode::OK, |code| code)
}