custom errors

This commit is contained in:
catvayor 2024-06-17 09:51:44 +02:00
parent 6dd6e46aab
commit bf9d82ed9f
25 changed files with 414 additions and 114 deletions

61
Cargo.lock generated
View file

@ -122,6 +122,16 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "bstr"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706"
dependencies = [
"memchr",
"serde",
]
[[package]] [[package]]
name = "bytemuck" name = "bytemuck"
version = "1.16.0" version = "1.16.0"
@ -432,6 +442,19 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "globset"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
dependencies = [
"aho-corasick",
"bstr",
"log",
"regex-automata 0.4.6",
"regex-syntax 0.8.3",
]
[[package]] [[package]]
name = "h2" name = "h2"
version = "0.3.26" version = "0.3.26"
@ -1154,6 +1177,41 @@ dependencies = [
"uncased", "uncased",
] ]
[[package]]
name = "rust-embed"
version = "8.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19549741604902eb99a7ed0ee177a0663ee1eda51a29f71401f166e47e77806a"
dependencies = [
"rust-embed-impl",
"rust-embed-utils",
"walkdir",
]
[[package]]
name = "rust-embed-impl"
version = "8.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb9f96e283ec64401f30d3df8ee2aaeb2561f34c824381efa24a35f79bf40ee4"
dependencies = [
"proc-macro2",
"quote",
"rust-embed-utils",
"syn",
"walkdir",
]
[[package]]
name = "rust-embed-utils"
version = "8.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38c74a686185620830701348de757fd36bef4aa9680fd23c49fc539ddcc1af32"
dependencies = [
"globset",
"sha2",
"walkdir",
]
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.24" version = "0.1.24"
@ -1564,11 +1622,12 @@ dependencies = [
[[package]] [[package]]
name = "traque" name = "traque"
version = "0.1.0" version = "0.2.4"
dependencies = [ dependencies = [
"rand", "rand",
"rocket", "rocket",
"rocket_dyn_templates", "rocket_dyn_templates",
"rust-embed",
] ]
[[package]] [[package]]

View file

@ -1,6 +1,6 @@
[package] [package]
name = "traque" name = "traque"
version = "0.1.0" version = "0.2.4"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -8,6 +8,10 @@ edition = "2021"
[dependencies] [dependencies]
rand = "0.8.5" rand = "0.8.5"
[dependencies.rust-embed]
version = "8.4.0"
features = ["include-exclude"]
[dependencies.rocket] [dependencies.rocket]
version = "0.5.0" version = "0.5.0"
features = ["json"] features = ["json"]

View file

@ -3,13 +3,16 @@ extern crate rocket;
use rocket::{ use rocket::{
fairing::AdHoc, fairing::AdHoc,
fs::{relative, FileServer}, fs::{relative, FileServer},
response::stream::Event, http::Status,
response::{content, stream::Event},
tokio::{ tokio::{
self, select, self, select,
time::{self, Duration}, time::{self, Duration},
}, },
Request,
}; };
use rocket_dyn_templates::Template; use rocket_dyn_templates::Template;
use rust_embed::Embed;
use std::{ use std::{
collections::VecDeque, collections::VecDeque,
sync::{Arc, RwLock}, sync::{Arc, RwLock},
@ -68,6 +71,27 @@ fn clean_expired_evt(
} }
} }
#[derive(Embed)]
#[folder = "static/errors"]
#[include = "*.html"]
#[exclude = "*.jpg"]
struct ErrorPages;
#[catch(default)]
fn handler(status: Status, _: &Request) -> content::RawHtml<String> {
content::RawHtml(
std::str::from_utf8(
ErrorPages::get(format!("{}.html", status.code).as_str())
//501 not implemented
.unwrap_or(ErrorPages::get("501.html").unwrap())
.data
.as_ref(),
)
.unwrap()
.to_string(),
)
}
#[launch] #[launch]
async fn rocket() -> _ { async fn rocket() -> _ {
let rocket = rocket::build(); let rocket = rocket::build();
@ -106,7 +130,8 @@ async fn rocket() -> _ {
.manage(admin_evt_queue.clone()) .manage(admin_evt_queue.clone())
.mount("/", routes![index]) .mount("/", routes![index])
.mount("/track", track::routes()) .mount("/track", track::routes())
.mount("/admin", admin::routes()); .mount("/admin", admin::routes())
.register("/", catchers![handler]);
if config.serve_static { if config.serve_static {
rocket = rocket.mount("/", FileServer::from(relative!("static"))); rocket = rocket.mount("/", FileServer::from(relative!("static")));
} }

View file

@ -1,4 +1,5 @@
use rocket::{ use rocket::{
http::Status,
response::stream::{Event, EventStream}, response::stream::{Event, EventStream},
tokio::{ tokio::{
self, select, self, select,
@ -10,15 +11,20 @@ use rocket_dyn_templates::{context, Template};
use crate::global::{TrackedState::*, *}; use crate::global::{TrackedState::*, *};
#[get("/")]
fn no_id() -> Status {
Status::ImATeapot
}
#[get("/<id>?<gpslog>&<dbg>")] #[get("/<id>?<gpslog>&<dbg>")]
fn tracked_view( fn tracked_view(
id: &str, id: &str,
gpslog: Option<bool>, gpslog: Option<bool>,
dbg: Option<bool>, dbg: Option<bool>,
tracking: &State<Tracking>, tracking: &State<Tracking>,
) -> Option<Template> { ) -> Result<Template, Status> {
if let Some(tracked) = tracking.get(&id.to_string()) { if let Some(tracked) = tracking.get(&id.to_string()) {
Some(Template::render( Ok(Template::render(
match tracked.read().unwrap().state { match tracked.read().unwrap().state {
Vieux { .. } => "vieux", Vieux { .. } => "vieux",
Conscrit { .. } => "conscrit", Conscrit { .. } => "conscrit",
@ -31,7 +37,7 @@ fn tracked_view(
}, },
)) ))
} else { } else {
None Err(Status::BadRequest)
} }
} }
@ -41,10 +47,10 @@ fn tracked_events<'a>(
evt_queue: &'a State<TrackingEventQueue>, evt_queue: &'a State<TrackingEventQueue>,
config: &State<Config>, config: &State<Config>,
mut shutdown: Shutdown, mut shutdown: Shutdown,
) -> Option<EventStream![Event + 'a]> { ) -> Result<EventStream![Event + 'a], Status> {
if evt_queue.contains_key(&id.to_string()) { if evt_queue.contains_key(&id.to_string()) {
let timeout = Duration::from_millis(config.event_timeout); let timeout = Duration::from_millis(config.event_timeout);
Some(EventStream! { Ok(EventStream! {
let mut interval = time::interval(timeout); let mut interval = time::interval(timeout);
loop { loop {
select!{ select!{
@ -59,7 +65,7 @@ fn tracked_events<'a>(
} }
}) })
} else { } else {
None Err(Status::BadRequest)
} }
} }
@ -71,10 +77,13 @@ fn store_pos(
tracking: &State<Tracking>, tracking: &State<Tracking>,
evt_queues: &State<TrackingEventQueue>, evt_queues: &State<TrackingEventQueue>,
admin_queue: &State<AdminEventQueue>, admin_queue: &State<AdminEventQueue>,
) { ) -> Status {
if let Some(tracked) = tracking.get(&id.to_string()) { if let Some(tracked) = tracking.get(&id.to_string()) {
tracked.write().unwrap().pos = (lat, long); tracked.write().unwrap().pos = (lat, long);
state_update(&tracked.read().unwrap(), &evt_queues, &admin_queue); state_update(&tracked.read().unwrap(), &evt_queues, &admin_queue);
Status::Accepted
} else {
Status::BadRequest
} }
} }
@ -86,8 +95,9 @@ fn set_state(
tracking: &State<Tracking>, tracking: &State<Tracking>,
evt_queues: &State<TrackingEventQueue>, evt_queues: &State<TrackingEventQueue>,
admin_queue: &State<AdminEventQueue>, admin_queue: &State<AdminEventQueue>,
) -> Option<()> { ) -> Status {
let tracked = &mut tracking.get(&id.to_string()).unwrap().write().unwrap(); if let Some(tracked) = tracking.get(&id.to_string()) {
let tracked = &mut tracked.write().unwrap();
if let Vieux { if let Vieux {
ref mut invisible, ref mut invisible,
ref mut color, ref mut color,
@ -96,9 +106,12 @@ fn set_state(
*invisible = inv; *invisible = inv;
*color = col; *color = col;
state_update(&tracked, &evt_queues, &admin_queue); state_update(&tracked, &evt_queues, &admin_queue);
Some(()) Status::Accepted
} else { } else {
None Status::MethodNotAllowed
}
} else {
Status::BadRequest
} }
} }
@ -109,8 +122,9 @@ pub async fn activate_invisibility(
evt_queues: &State<TrackingEventQueue>, evt_queues: &State<TrackingEventQueue>,
admin_queue: &State<AdminEventQueue>, admin_queue: &State<AdminEventQueue>,
config: &State<Config>, config: &State<Config>,
) -> Option<()> { ) -> Status {
let tracked = &mut tracking.get(&id.to_string()).unwrap().write().unwrap(); if let Some(tracked) = tracking.get(&id.to_string()) {
let tracked = &mut tracked.write().unwrap();
if let Conscrit { if let Conscrit {
ref mut invisible, ref mut invisible,
ref mut invisibility_codes, ref mut invisibility_codes,
@ -140,12 +154,15 @@ pub async fn activate_invisibility(
&admin_clone, &admin_clone,
); );
}); });
Some(()) Status::Accepted
} else { } else {
None Status::PaymentRequired
} }
} else { } else {
None Status::MethodNotAllowed
}
} else {
Status::BadRequest
} }
} }
@ -156,8 +173,9 @@ pub async fn activate_blur(
evt_queues: &State<TrackingEventQueue>, evt_queues: &State<TrackingEventQueue>,
admin_queue: &State<AdminEventQueue>, admin_queue: &State<AdminEventQueue>,
config: &State<Config>, config: &State<Config>,
) -> Option<()> { ) -> Status {
let tracked = &mut tracking.get(&id.to_string()).unwrap().write().unwrap(); if let Some(tracked) = tracking.get(&id.to_string()) {
let tracked = &mut tracked.write().unwrap();
if let Conscrit { if let Conscrit {
ref mut blurred, ref mut blurred,
ref mut blur_codes, ref mut blur_codes,
@ -187,12 +205,15 @@ pub async fn activate_blur(
&admin_clone, &admin_clone,
); );
}); });
Some(()) Status::Accepted
} else { } else {
None Status::PaymentRequired
} }
} else { } else {
None Status::MethodNotAllowed
}
} else {
Status::BadRequest
} }
} }
@ -204,5 +225,6 @@ pub fn routes() -> Vec<Route> {
set_state, set_state,
activate_invisibility, activate_invisibility,
activate_blur, activate_blur,
no_id,
] ]
} }

19
static/errors/400.html Normal file
View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="color-scheme" content="light dark">
<title>400 Bad Request</title>
</head>
<body align="center">
<div role="main" align="center">
<h1>400 Bad Request</h1>
<img src="/errors/cat/400.jpg"/>
<p>Conscrit ! Cet identifiant ne correspond à aucune équipe.</p>
<hr />
</div>
<div role="contentinfo" align="center">
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
</div>
</body>
</html>

19
static/errors/401.html Normal file
View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="color-scheme" content="light dark">
<title>401 Unauthorized</title>
</head>
<body align="center">
<div role="main" align="center">
<h1>401 Unauthorized</h1>
<img src="/errors/cat/401.jpg"/>
<p>Il faut s'identifié pour accéder à cette ressource.</p>
<hr />
</div>
<div role="contentinfo" align="center">
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
</div>
</body>
</html>

19
static/errors/402.html Normal file
View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="color-scheme" content="light dark">
<title>402 Payment Required</title>
</head>
<body align="center">
<div role="main" align="center">
<h1>402 Payment Required</h1>
<img src="/errors/cat/402.jpg"/>
<p>Toute les utilisations de ce bonus ont été utilisées.</p>
<hr />
</div>
<div role="contentinfo" align="center">
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
</div>
</body>
</html>

19
static/errors/404.html Normal file
View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="color-scheme" content="light dark">
<title>404 Not Found</title>
</head>
<body align="center">
<div role="main" align="center">
<h1>404 Not Found</h1>
<img src="/errors/cat/404.jpg"/>
<p>Page non trouvé</p>
<hr />
</div>
<div role="contentinfo" align="center">
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
</div>
</body>
</html>

19
static/errors/405.html Normal file
View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="color-scheme" content="light dark">
<title>405 Method Not Allowed</title>
</head>
<body align="center">
<div role="main" align="center">
<h1>405 Method Not Allowed</h1>
<img src="/errors/cat/405.jpg"/>
<p>Cette équipe n'a pas le droit d'utiliser cet endpoint.</p>
<hr />
</div>
<div role="contentinfo" align="center">
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
</div>
</body>
</html>

19
static/errors/418.html Normal file
View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="color-scheme" content="light dark">
<title>418 Im a teapot</title>
</head>
<body align="center">
<div role="main" align="center">
<h1>418 Im a teapot</h1>
<img src="/errors/cat/418.jpg"/>
<p>Il y a quelque-chose ici, mais je montrerai rien.</p>
<hr />
</div>
<div role="contentinfo" align="center">
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
</div>
</body>
</html>

19
static/errors/498.html Normal file
View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="color-scheme" content="light dark">
<title>498 Token expired/invalid</title>
</head>
<body align="center">
<div role="main" align="center">
<h1>498 Token expired/invalid</h1>
<img src="/errors/cat/498.jpg"/>
<p>Le token d'authentification est invalide.</p>
<hr />
</div>
<div role="contentinfo" align="center">
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
</div>
</body>
</html>

19
static/errors/500.html Normal file
View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="color-scheme" content="light dark">
<title>500 Internal Server Error</title>
</head>
<body align="center">
<div role="main" align="center">
<h1>500 Internal Server Error</h1>
<img src="/errors/cat/500.jpg"/>
<p>Erreur Interne</p>
<hr />
</div>
<div role="contentinfo" align="center">
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
</div>
</body>
</html>

19
static/errors/501.html Normal file
View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="color-scheme" content="light dark">
<title>501 Not Implemented</title>
</head>
<body align="center">
<div role="main" align="center">
<h1>501 Not Implemented</h1>
<img src="/errors/cat/501.jpg"/>
<p>Une erreur inconnue a été rencontré.</p>
<hr />
</div>
<div role="contentinfo" align="center">
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
</div>
</body>
</html>

19
static/errors/503.html Normal file
View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
<meta name="color-scheme" content="light dark">
<title>503 Service Unavailable</title>
</head>
<body align="center">
<div role="main" align="center">
<h1>503 Service Unavailable</h1>
<img src="/errors/cat/503.jpg"/>
<p>La traque n'est pas encore prête, on arrive bientôt...</p>
<hr />
</div>
<div role="contentinfo" align="center">
<small>Crédit à <a href="https://http.cat">http.cat</a> pour l'image.</small>
</div>
</body>
</html>

BIN
static/errors/cat/400.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
static/errors/cat/401.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
static/errors/cat/402.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
static/errors/cat/404.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
static/errors/cat/405.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
static/errors/cat/418.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
static/errors/cat/498.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

BIN
static/errors/cat/500.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
static/errors/cat/501.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
static/errors/cat/503.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB