-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: [#157] extract API contexts
- Loading branch information
1 parent
8e387cd
commit 19d33b4
Showing
28 changed files
with
364 additions
and
268 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
use std::str::FromStr; | ||
use std::sync::Arc; | ||
use std::time::Duration; | ||
|
||
use axum::extract::{Path, State}; | ||
use axum::response::Response; | ||
use serde::Deserialize; | ||
|
||
use super::responses::{ | ||
auth_key_response, failed_to_delete_key_response, failed_to_generate_key_response, failed_to_reload_keys_response, | ||
}; | ||
use crate::apis::context::auth_key::resources::AuthKey; | ||
use crate::apis::responses::{invalid_auth_key_param_response, ok_response}; | ||
use crate::tracker::auth::Key; | ||
use crate::tracker::Tracker; | ||
|
||
pub async fn generate_auth_key_handler(State(tracker): State<Arc<Tracker>>, Path(seconds_valid_or_key): Path<u64>) -> Response { | ||
let seconds_valid = seconds_valid_or_key; | ||
match tracker.generate_auth_key(Duration::from_secs(seconds_valid)).await { | ||
Ok(auth_key) => auth_key_response(&AuthKey::from(auth_key)), | ||
Err(e) => failed_to_generate_key_response(e), | ||
} | ||
} | ||
|
||
#[derive(Deserialize)] | ||
pub struct KeyParam(String); | ||
|
||
pub async fn delete_auth_key_handler( | ||
State(tracker): State<Arc<Tracker>>, | ||
Path(seconds_valid_or_key): Path<KeyParam>, | ||
) -> Response { | ||
match Key::from_str(&seconds_valid_or_key.0) { | ||
Err(_) => invalid_auth_key_param_response(&seconds_valid_or_key.0), | ||
Ok(key) => match tracker.remove_auth_key(&key.to_string()).await { | ||
Ok(_) => ok_response(), | ||
Err(e) => failed_to_delete_key_response(e), | ||
}, | ||
} | ||
} | ||
|
||
pub async fn reload_keys_handler(State(tracker): State<Arc<Tracker>>) -> Response { | ||
match tracker.load_keys_from_database().await { | ||
Ok(_) => ok_response(), | ||
Err(e) => failed_to_reload_keys_response(e), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
pub mod handlers; | ||
pub mod resources; | ||
pub mod responses; | ||
pub mod routes; |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
use std::error::Error; | ||
|
||
use axum::http::{header, StatusCode}; | ||
use axum::response::{IntoResponse, Response}; | ||
|
||
use crate::apis::context::auth_key::resources::AuthKey; | ||
use crate::apis::responses::unhandled_rejection_response; | ||
|
||
/// # Panics | ||
/// | ||
/// Will panic if it can't convert the `AuthKey` resource to json | ||
#[must_use] | ||
pub fn auth_key_response(auth_key: &AuthKey) -> Response { | ||
( | ||
StatusCode::OK, | ||
[(header::CONTENT_TYPE, "application/json; charset=utf-8")], | ||
serde_json::to_string(auth_key).unwrap(), | ||
) | ||
.into_response() | ||
} | ||
|
||
#[must_use] | ||
pub fn failed_to_generate_key_response<E: Error>(e: E) -> Response { | ||
unhandled_rejection_response(format!("failed to generate key: {e}")) | ||
} | ||
|
||
#[must_use] | ||
pub fn failed_to_delete_key_response<E: Error>(e: E) -> Response { | ||
unhandled_rejection_response(format!("failed to delete key: {e}")) | ||
} | ||
|
||
#[must_use] | ||
pub fn failed_to_reload_keys_response<E: Error>(e: E) -> Response { | ||
unhandled_rejection_response(format!("failed to reload keys: {e}")) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
use std::sync::Arc; | ||
|
||
use axum::routing::{get, post}; | ||
use axum::Router; | ||
|
||
use super::handlers::{delete_auth_key_handler, generate_auth_key_handler, reload_keys_handler}; | ||
use crate::tracker::Tracker; | ||
|
||
pub fn add(router: Router, tracker: Arc<Tracker>) -> Router { | ||
// Keys | ||
router | ||
.route( | ||
// code-review: Axum does not allow two routes with the same path but different path variable name. | ||
// In the new major API version, `seconds_valid` should be a POST form field so that we will have two paths: | ||
// POST /api/key | ||
// DELETE /api/key/:key | ||
"/api/key/:seconds_valid_or_key", | ||
post(generate_auth_key_handler) | ||
.with_state(tracker.clone()) | ||
.delete(delete_auth_key_handler) | ||
.with_state(tracker.clone()), | ||
) | ||
// Keys command | ||
.route("/api/keys/reload", get(reload_keys_handler).with_state(tracker)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
pub mod auth_key; | ||
pub mod peer; | ||
pub mod stats; | ||
pub mod torrent; | ||
pub mod whitelist; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
use std::sync::Arc; | ||
|
||
use axum::extract::State; | ||
use axum::response::Json; | ||
|
||
use super::resources::Stats; | ||
use super::responses::stats_response; | ||
use crate::tracker::services::statistics::get_metrics; | ||
use crate::tracker::Tracker; | ||
|
||
pub async fn get_stats_handler(State(tracker): State<Arc<Tracker>>) -> Json<Stats> { | ||
stats_response(get_metrics(tracker.clone()).await) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
pub mod handlers; | ||
pub mod resources; | ||
pub mod responses; | ||
pub mod routes; |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
use axum::response::Json; | ||
|
||
use super::resources::Stats; | ||
use crate::tracker::services::statistics::TrackerMetrics; | ||
|
||
pub fn stats_response(tracker_metrics: TrackerMetrics) -> Json<Stats> { | ||
Json(Stats::from(tracker_metrics)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
use std::sync::Arc; | ||
|
||
use axum::routing::get; | ||
use axum::Router; | ||
|
||
use super::handlers::get_stats_handler; | ||
use crate::tracker::Tracker; | ||
|
||
pub fn add(router: Router, tracker: Arc<Tracker>) -> Router { | ||
router.route("/api/stats", get(get_stats_handler).with_state(tracker)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
use std::fmt; | ||
use std::str::FromStr; | ||
use std::sync::Arc; | ||
|
||
use axum::extract::{Path, Query, State}; | ||
use axum::response::{IntoResponse, Json, Response}; | ||
use serde::{de, Deserialize, Deserializer}; | ||
|
||
use super::resources::torrent::ListItem; | ||
use super::responses::{torrent_info_response, torrent_list_response, torrent_not_known_response}; | ||
use crate::apis::responses::invalid_info_hash_param_response; | ||
use crate::apis::InfoHashParam; | ||
use crate::protocol::info_hash::InfoHash; | ||
use crate::tracker::services::torrent::{get_torrent_info, get_torrents, Pagination}; | ||
use crate::tracker::Tracker; | ||
|
||
pub async fn get_torrent_handler(State(tracker): State<Arc<Tracker>>, Path(info_hash): Path<InfoHashParam>) -> Response { | ||
match InfoHash::from_str(&info_hash.0) { | ||
Err(_) => invalid_info_hash_param_response(&info_hash.0), | ||
Ok(info_hash) => match get_torrent_info(tracker.clone(), &info_hash).await { | ||
Some(info) => torrent_info_response(info).into_response(), | ||
None => torrent_not_known_response(), | ||
}, | ||
} | ||
} | ||
|
||
#[derive(Deserialize)] | ||
pub struct PaginationParams { | ||
#[serde(default, deserialize_with = "empty_string_as_none")] | ||
pub offset: Option<u32>, | ||
pub limit: Option<u32>, | ||
} | ||
|
||
pub async fn get_torrents_handler( | ||
State(tracker): State<Arc<Tracker>>, | ||
pagination: Query<PaginationParams>, | ||
) -> Json<Vec<ListItem>> { | ||
torrent_list_response( | ||
&get_torrents( | ||
tracker.clone(), | ||
&Pagination::new_with_options(pagination.0.offset, pagination.0.limit), | ||
) | ||
.await, | ||
) | ||
} | ||
|
||
/// Serde deserialization decorator to map empty Strings to None, | ||
fn empty_string_as_none<'de, D, T>(de: D) -> Result<Option<T>, D::Error> | ||
where | ||
D: Deserializer<'de>, | ||
T: FromStr, | ||
T::Err: fmt::Display, | ||
{ | ||
let opt = Option::<String>::deserialize(de)?; | ||
match opt.as_deref() { | ||
None | Some("") => Ok(None), | ||
Some(s) => FromStr::from_str(s).map_err(de::Error::custom).map(Some), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
pub mod handlers; | ||
pub mod resources; | ||
pub mod responses; | ||
pub mod routes; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
pub mod peer; | ||
pub mod torrent; |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
use axum::response::{IntoResponse, Json, Response}; | ||
use serde_json::json; | ||
|
||
use super::resources::torrent::{ListItem, Torrent}; | ||
use crate::tracker::services::torrent::{BasicInfo, Info}; | ||
|
||
pub fn torrent_list_response(basic_infos: &[BasicInfo]) -> Json<Vec<ListItem>> { | ||
Json(ListItem::new_vec(basic_infos)) | ||
} | ||
|
||
pub fn torrent_info_response(info: Info) -> Json<Torrent> { | ||
Json(Torrent::from(info)) | ||
} | ||
|
||
#[must_use] | ||
pub fn torrent_not_known_response() -> Response { | ||
Json(json!("torrent not known")).into_response() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
use std::sync::Arc; | ||
|
||
use axum::routing::get; | ||
use axum::Router; | ||
|
||
use super::handlers::{get_torrent_handler, get_torrents_handler}; | ||
use crate::tracker::Tracker; | ||
|
||
pub fn add(router: Router, tracker: Arc<Tracker>) -> Router { | ||
// Torrents | ||
router | ||
.route( | ||
"/api/torrent/:info_hash", | ||
get(get_torrent_handler).with_state(tracker.clone()), | ||
) | ||
.route("/api/torrents", get(get_torrents_handler).with_state(tracker)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
use std::str::FromStr; | ||
use std::sync::Arc; | ||
|
||
use axum::extract::{Path, State}; | ||
use axum::response::Response; | ||
|
||
use super::responses::{ | ||
failed_to_reload_whitelist_response, failed_to_remove_torrent_from_whitelist_response, failed_to_whitelist_torrent_response, | ||
}; | ||
use crate::apis::responses::{invalid_info_hash_param_response, ok_response}; | ||
use crate::apis::InfoHashParam; | ||
use crate::protocol::info_hash::InfoHash; | ||
use crate::tracker::Tracker; | ||
|
||
pub async fn add_torrent_to_whitelist_handler( | ||
State(tracker): State<Arc<Tracker>>, | ||
Path(info_hash): Path<InfoHashParam>, | ||
) -> Response { | ||
match InfoHash::from_str(&info_hash.0) { | ||
Err(_) => invalid_info_hash_param_response(&info_hash.0), | ||
Ok(info_hash) => match tracker.add_torrent_to_whitelist(&info_hash).await { | ||
Ok(_) => ok_response(), | ||
Err(e) => failed_to_whitelist_torrent_response(e), | ||
}, | ||
} | ||
} | ||
|
||
pub async fn remove_torrent_from_whitelist_handler( | ||
State(tracker): State<Arc<Tracker>>, | ||
Path(info_hash): Path<InfoHashParam>, | ||
) -> Response { | ||
match InfoHash::from_str(&info_hash.0) { | ||
Err(_) => invalid_info_hash_param_response(&info_hash.0), | ||
Ok(info_hash) => match tracker.remove_torrent_from_whitelist(&info_hash).await { | ||
Ok(_) => ok_response(), | ||
Err(e) => failed_to_remove_torrent_from_whitelist_response(e), | ||
}, | ||
} | ||
} | ||
|
||
pub async fn reload_whitelist_handler(State(tracker): State<Arc<Tracker>>) -> Response { | ||
match tracker.load_whitelist_from_database().await { | ||
Ok(_) => ok_response(), | ||
Err(e) => failed_to_reload_whitelist_response(e), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
pub mod handlers; | ||
pub mod responses; | ||
pub mod routes; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
use std::error::Error; | ||
|
||
use axum::response::Response; | ||
|
||
use crate::apis::responses::unhandled_rejection_response; | ||
|
||
#[must_use] | ||
pub fn failed_to_remove_torrent_from_whitelist_response<E: Error>(e: E) -> Response { | ||
unhandled_rejection_response(format!("failed to remove torrent from whitelist: {e}")) | ||
} | ||
|
||
#[must_use] | ||
pub fn failed_to_whitelist_torrent_response<E: Error>(e: E) -> Response { | ||
unhandled_rejection_response(format!("failed to whitelist torrent: {e}")) | ||
} | ||
|
||
#[must_use] | ||
pub fn failed_to_reload_whitelist_response<E: Error>(e: E) -> Response { | ||
unhandled_rejection_response(format!("failed to reload whitelist: {e}")) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
use std::sync::Arc; | ||
|
||
use axum::routing::{delete, get, post}; | ||
use axum::Router; | ||
|
||
use super::handlers::{add_torrent_to_whitelist_handler, reload_whitelist_handler, remove_torrent_from_whitelist_handler}; | ||
use crate::tracker::Tracker; | ||
|
||
pub fn add(router: Router, tracker: Arc<Tracker>) -> Router { | ||
router | ||
// Whitelisted torrents | ||
.route( | ||
"/api/whitelist/:info_hash", | ||
post(add_torrent_to_whitelist_handler).with_state(tracker.clone()), | ||
) | ||
.route( | ||
"/api/whitelist/:info_hash", | ||
delete(remove_torrent_from_whitelist_handler).with_state(tracker.clone()), | ||
) | ||
// Whitelist commands | ||
.route("/api/whitelist/reload", get(reload_whitelist_handler).with_state(tracker)) | ||
} |
Oops, something went wrong.