headless_lms_server/controllers/main_frontend/
time.rs1use crate::prelude::*;
6use chrono::{SecondsFormat, Utc};
7
8pub async fn get_current_time() -> ControllerResult<HttpResponse> {
15 let server_time = Utc::now().to_rfc3339_opts(SecondsFormat::Millis, true);
16 let token = skip_authorize();
17
18 token.authorized_ok(
19 HttpResponse::Ok()
20 .insert_header((
21 "Cache-Control",
22 "no-store, no-cache, must-revalidate, max-age=0",
23 ))
24 .insert_header(("Pragma", "no-cache"))
25 .insert_header(("Expires", "0"))
26 .json(server_time),
27 )
28}
29
30pub fn _add_routes(cfg: &mut ServiceConfig) {
31 cfg.route("", web::get().to(get_current_time));
32}
33
34#[cfg(test)]
35mod tests {
36 use super::*;
37 use actix_web::{App, test, web};
38
39 #[actix_web::test]
40 async fn returns_non_cacheable_rfc3339_json_string() {
41 let app = test::init_service(App::new().service(web::scope("/api/v0").service(
42 web::scope("/main-frontend").service(web::scope("/time").configure(_add_routes)),
43 )))
44 .await;
45
46 let req = test::TestRequest::with_uri("/api/v0/main-frontend/time").to_request();
47 let resp = test::call_service(&app, req).await;
48
49 assert!(resp.status().is_success());
50 assert_eq!(
51 resp.headers().get("Cache-Control").unwrap(),
52 "no-store, no-cache, must-revalidate, max-age=0"
53 );
54 assert_eq!(resp.headers().get("Pragma").unwrap(), "no-cache");
55 assert_eq!(resp.headers().get("Expires").unwrap(), "0");
56
57 let body: String = test::read_body_json(resp).await;
58 assert!(chrono::DateTime::parse_from_rfc3339(&body).is_ok());
59
60 let parsed = chrono::DateTime::parse_from_rfc3339(&body).unwrap();
61 let server_utc = parsed.with_timezone(&chrono::Utc);
62 let now = chrono::Utc::now();
63 let diff = (server_utc - now).abs();
64 assert!(
65 diff < chrono::Duration::seconds(5),
66 "server time should be close to now"
67 );
68 }
69}