+1
Cargo.lock
+1
Cargo.lock
+1
Cargo.toml
+1
Cargo.toml
+20
-4
src/main.rs
+20
-4
src/main.rs
···
1
-
use axum::{Router, routing::get};
2
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
3
4
#[tokio::main]
5
async fn main() {
6
-
let app = Router::new().route("/", get(handler));
7
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 7878);
8
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
9
println!("listening on {}", addr);
10
axum::serve(listener, app).await.unwrap();
11
}
12
13
-
async fn handler() -> &'static str {
14
-
"hello, world!"
15
}
···
1
+
use axum::extract::Path;
2
+
use axum::{Router, middleware, routing::get};
3
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
4
+
use std::time;
5
+
6
+
mod unlock;
7
8
#[tokio::main]
9
async fn main() {
10
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 7878);
11
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
12
println!("listening on {}", addr);
13
+
14
+
let now = time::Instant::now();
15
+
let daily = time::Duration::from_secs(24 * 60 * 60);
16
+
let state = unlock::Unlock::new(now, daily);
17
+
18
+
let app =
19
+
Router::new()
20
+
.route("/day/{id}", get(handler))
21
+
.route_layer(middleware::from_fn_with_state(
22
+
state.clone(),
23
+
unlock::unlock,
24
+
));
25
+
26
axum::serve(listener, app).await.unwrap();
27
}
28
29
+
async fn handler(Path(id): Path<u32>) -> String {
30
+
format!("hello day {id}")
31
}
+40
src/unlock.rs
+40
src/unlock.rs
···
···
1
+
use axum::extract::{Path, Request, State};
2
+
use axum::http;
3
+
use axum::{
4
+
middleware,
5
+
response::{self, IntoResponse},
6
+
};
7
+
use std::time;
8
+
9
+
#[derive(Clone)]
10
+
pub struct Unlock {
11
+
start: time::Instant,
12
+
interval: time::Duration,
13
+
}
14
+
15
+
impl Unlock {
16
+
pub fn new(start: time::Instant, interval: time::Duration) -> Self {
17
+
Self { start, interval }
18
+
}
19
+
}
20
+
21
+
pub async fn unlock(
22
+
Path(day): Path<u32>,
23
+
State(unlocker): State<Unlock>,
24
+
request: Request,
25
+
next: middleware::Next,
26
+
) -> response::Response {
27
+
let deadline = unlocker.start + unlocker.interval * day;
28
+
let now = time::Instant::now();
29
+
if now >= deadline {
30
+
return next.run(request).await;
31
+
}
32
+
33
+
let time_remaining = deadline.saturating_duration_since(now);
34
+
let error_response = axum::Json(serde_json::json!({
35
+
"error": "Route Locked",
36
+
"time_remaining_seconds": time_remaining.as_secs(),
37
+
}));
38
+
39
+
(http::StatusCode::FORBIDDEN, error_response).into_response()
40
+
}