veloren_server_cli/web/ui/
mod.rs1use axum::{
2 Router,
3 extract::{ConnectInfo, State},
4 http::{HeaderMap, HeaderValue, header::SET_COOKIE},
5 response::{Html, IntoResponse},
6 routing::get,
7};
8use std::net::SocketAddr;
9
10pub mod api;
11
12#[derive(Clone)]
14struct UiApiToken {
15 secret_token: String,
16}
17
18pub fn router(secret_token: String) -> Router {
19 let token = UiApiToken { secret_token };
20 Router::new().route("/", get(ui)).with_state(token)
21}
22
23async fn ui(
24 ConnectInfo(addr): ConnectInfo<SocketAddr>,
25 headers: HeaderMap,
26 State(token): State<UiApiToken>,
27) -> impl IntoResponse {
28 const X_FORWARDED_FOR: &'_ str = "X-Forwarded-For";
29 if !addr.ip().is_loopback()
30 || headers.contains_key(axum::http::header::FORWARDED)
31 || headers.contains_key(X_FORWARDED_FOR)
32 {
33 return Html(
34 r#"<!DOCTYPE html>
35<html>
36<body>
37Ui is only accessible from 127.0.0.1. Usage of proxies is forbidden.
38</body>
39</html>
40 "#
41 .to_string(),
42 )
43 .into_response();
44 }
45
46 let js = include_str!("./ui.js");
47 let css = include_str!("./ui.css");
48 let inner = include_str!("./ui.html");
49
50 let mut response = Html(format!(
51 r#"<!DOCTYPE html>
52<html>
53<head>
54<script type="text/javascript">
55{js}
56</script>
57<style>
58{css}
59</style>
60</head>
61<body>
62{inner}
63</body>
64</html>"#
65 ))
66 .into_response();
67
68 let cookie = format!("X-Secret-Token={}; SameSite=Strict", token.secret_token);
69
70 response.headers_mut().insert(
73 SET_COOKIE,
74 HeaderValue::from_str(&cookie).expect("An invalid secret-token for ui was provided"),
75 );
76 response
77}