85 lines
5.0 KiB
Rust
85 lines
5.0 KiB
Rust
async fn not_found(State(state): State<AppState>, headers: HeaderMap) -> Response {
|
|
let base = request_base_path(&state, &headers);
|
|
let home = if base.is_empty() { "/".to_owned() } else { format!("{base}/") };
|
|
let body = NOT_FOUND_HTML
|
|
.replace("__GREE_BASE_PATH__", &base)
|
|
.replace("__GREE_HOME_PATH__", &home)
|
|
.replace("__GREE_THEME_INIT_ASSET__", &format!("{base}{THEME_INIT_ASSET_PATH}"))
|
|
.replace("__GREE_STYLES_ASSET__", &format!("{base}{STYLES_CSS_ASSET_PATH}"));
|
|
let mut response = Response::new(Body::from(body));
|
|
*response.status_mut() = StatusCode::NOT_FOUND;
|
|
response.headers_mut().insert(header::CONTENT_TYPE, HeaderValue::from_static("text/html; charset=utf-8"));
|
|
response.headers_mut().insert(header::CACHE_CONTROL, HeaderValue::from_static("private, no-store, no-cache, must-revalidate"));
|
|
response
|
|
}
|
|
|
|
async fn index(State(state): State<AppState>, headers: HeaderMap) -> Response {
|
|
let base = request_base_path(&state, &headers);
|
|
let body = INDEX_HTML
|
|
.replace("__GREE_BASE_PATH__", &base)
|
|
.replace("__GREE_APP_ASSET__", &format!("{base}{APP_JS_ASSET_PATH}"))
|
|
.replace("__GREE_THEME_INIT_ASSET__", &format!("{base}{THEME_INIT_ASSET_PATH}"))
|
|
.replace("__GREE_STYLES_ASSET__", &format!("{base}{STYLES_CSS_ASSET_PATH}"));
|
|
let mut response = Response::new(Body::from(body));
|
|
response.headers_mut().insert(header::CONTENT_TYPE, HeaderValue::from_static("text/html; charset=utf-8"));
|
|
response.headers_mut().insert(header::CACHE_CONTROL, HeaderValue::from_static("private, no-store, no-cache, must-revalidate"));
|
|
response
|
|
}
|
|
|
|
fn request_base_path(state: &AppState, headers: &HeaderMap) -> String {
|
|
if !state.config.base_path.is_empty() {
|
|
state.config.base_path.clone()
|
|
} else {
|
|
forwarded_prefix(headers).unwrap_or_default()
|
|
}
|
|
}
|
|
|
|
fn forwarded_prefix(headers: &HeaderMap) -> Option<String> {
|
|
let raw = headers.get("x-forwarded-prefix")?.to_str().ok()?.split(',').next()?.trim();
|
|
if raw.is_empty() || raw == "/" { return Some(String::new()); }
|
|
if raw.contains('?') || raw.contains('#') || raw.split('/').any(|part| matches!(part, "." | "..")) { return None; }
|
|
Some(format!("/{}", raw.trim_matches('/')))
|
|
}
|
|
async fn app_js() -> Response { static_response(APP_JS, "application/javascript; charset=utf-8", "public, max-age=31536000, immutable") }
|
|
async fn app_js_legacy() -> Response { static_response(APP_JS, "application/javascript; charset=utf-8", "no-cache") }
|
|
async fn theme_init_js() -> Response { static_response(THEME_INIT_JS, "application/javascript; charset=utf-8", "public, max-age=31536000, immutable") }
|
|
async fn theme_init_js_legacy() -> Response { static_response(THEME_INIT_JS, "application/javascript; charset=utf-8", "no-cache") }
|
|
async fn styles_css() -> Response { static_response(STYLES_CSS, "text/css; charset=utf-8", "public, max-age=31536000, immutable") }
|
|
async fn styles_css_legacy() -> Response { static_response(STYLES_CSS, "text/css; charset=utf-8", "no-cache") }
|
|
async fn manifest() -> Response { static_response(MANIFEST, "application/manifest+json", "public, max-age=3600") }
|
|
async fn service_worker() -> Response {
|
|
let body = SERVICE_WORKER
|
|
.replace("__GREE_ASSET_CACHE__", ASSET_BUILD_ID)
|
|
.replace("__GREE_APP_ASSET__", APP_JS_ASSET_PATH)
|
|
.replace("__GREE_THEME_INIT_ASSET__", THEME_INIT_ASSET_PATH)
|
|
.replace("__GREE_STYLES_ASSET__", STYLES_CSS_ASSET_PATH);
|
|
owned_response(body, "application/javascript; charset=utf-8", "no-cache")
|
|
}
|
|
async fn favicon() -> Response { static_response(FAVICON, "image/svg+xml", "public, max-age=86400") }
|
|
async fn language_index() -> Response {
|
|
static_response(LANGUAGE_MANIFEST_JSON, "application/json; charset=utf-8", "no-cache")
|
|
}
|
|
async fn language_file(Path(file): Path<String>) -> Response {
|
|
let code = file.strip_suffix(".json").unwrap_or(&file);
|
|
if let Some((_, body)) = LANGUAGE_ASSETS.iter().find(|(language, _)| *language == code) {
|
|
return static_response(*body, "application/json; charset=utf-8", "no-cache");
|
|
}
|
|
let mut response = Response::new(Body::from("Language not found"));
|
|
*response.status_mut() = StatusCode::NOT_FOUND;
|
|
response.headers_mut().insert(header::CONTENT_TYPE, HeaderValue::from_static("text/plain; charset=utf-8"));
|
|
response
|
|
}
|
|
fn static_response(body: &'static str, content_type: &'static str, cache: &'static str) -> Response {
|
|
let mut response = Response::new(Body::from(body));
|
|
response.headers_mut().insert(header::CONTENT_TYPE, HeaderValue::from_static(content_type));
|
|
response.headers_mut().insert(header::CACHE_CONTROL, HeaderValue::from_static(cache));
|
|
response
|
|
}
|
|
|
|
fn owned_response(body: String, content_type: &'static str, cache: &'static str) -> Response {
|
|
let mut response = Response::new(Body::from(body));
|
|
response.headers_mut().insert(header::CONTENT_TYPE, HeaderValue::from_static(content_type));
|
|
response.headers_mut().insert(header::CACHE_CONTROL, HeaderValue::from_static(cache));
|
|
response
|
|
}
|