Skip to content

Commit 51afb87

Browse files
committed
docs: [#263] crate docs for apis mod
1 parent d164f90 commit 51afb87

File tree

8 files changed

+217
-5
lines changed

8 files changed

+217
-5
lines changed

cSpell.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"byteorder",
1717
"canonicalize",
1818
"canonicalized",
19+
"certbot",
1920
"chrono",
2021
"clippy",
2122
"completei",

src/servers/apis/mod.rs

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,159 @@
1+
//! The tracker REST API with all its versions.
2+
//!
3+
//! > **NOTICE**: This API should not be exposed directly to the internet, it is
4+
//! intended for internal use only.
5+
//!
6+
//! All endpoints require an authorization token which must be set in the
7+
//! configuration before running the tracker. The default configuration uses
8+
//! `?token=MyAccessToken`.
9+
//!
10+
//! Endpoints for the latest API: [v1](crate::servers::apis::v1).
11+
//!
12+
//! # Table of contents
13+
//!
14+
//! - [API versioning](#api-versioning)
15+
//! - [Enable the API](#enable-the-api)
16+
//! - [Authentication](#authentication)
17+
//! - [API endpoints](#api-endpoints)
18+
//!
19+
//! # API versioning
20+
//!
21+
//! The API is versioned and each version has its own module.
22+
//! The API server runs all the API versions on the same server using
23+
//! the same port. Currently there is only one API version: [v1](crate::servers::apis::v1)
24+
//! but a version [`v2`](https://github.com/torrust/torrust-tracker/issues/144)
25+
//! is planned.
26+
//!
27+
//! # Enable the API
28+
//!
29+
//! The configuration file has a `http_api` section that can be used to enable
30+
//! the API.
31+
//!
32+
//! ```toml
33+
//! [http_api]
34+
//! enabled = true
35+
//! bind_address = "0.0.0.0:1212"
36+
//! ssl_enabled = false
37+
//! ssl_cert_path = "./storage/ssl_certificates/localhost.crt"
38+
//! ssl_key_path = "./storage/ssl_certificates/localhost.key"
39+
//!
40+
//! [http_api.access_tokens]
41+
//! admin = "MyAccessToken"
42+
//! ```
43+
//!
44+
//! Refer to [torrust-tracker-configuration](https://docs.rs/torrust-tracker-configuration>)
45+
//! for more information about the API configuration.
46+
//!
47+
//! When you run the tracker with enabled API, you will see the following message:
48+
//!
49+
//! ```text
50+
//! Loading configuration from config file ./config.toml
51+
//! 023-03-28T12:19:24.963054069+01:00 [torrust_tracker::bootstrap::logging][INFO] logging initialized.
52+
//! ...
53+
//! 023-03-28T12:19:24.964138723+01:00 [torrust_tracker::bootstrap::jobs::tracker_apis][INFO] Starting Torrust APIs server on: http://0.0.0.0:1212
54+
//! ```
55+
//!
56+
//! The API server will be available on the address specified in the configuration.
57+
//!
58+
//! You can test the API by loading the following URL on a browser:
59+
//!
60+
//! <http://0.0.0.0:1212/api/v1/stats?token=MyAccessToken>
61+
//!
62+
//! Or using `curl`:
63+
//!
64+
//! ```bash
65+
//! $ curl -s http://0.0.0.0:1212/api/v1/stats?token=MyAccessToken | jq
66+
//! ```
67+
//!
68+
//! The response will be a JSON object. For example, the tracker statistics
69+
//! endpoint:
70+
//!
71+
//! ```json
72+
//! {
73+
//! "torrents": 0,
74+
//! "seeders": 0,
75+
//! "completed": 0,
76+
//! "leechers": 0,
77+
//! "tcp4_connections_handled": 0,
78+
//! "tcp4_announces_handled": 0,
79+
//! "tcp4_scrapes_handled": 0,
80+
//! "tcp6_connections_handled": 0,
81+
//! "tcp6_announces_handled": 0,
82+
//! "tcp6_scrapes_handled": 0,
83+
//! "udp4_connections_handled": 0,
84+
//! "udp4_announces_handled": 0,
85+
//! "udp4_scrapes_handled": 0,
86+
//! "udp6_connections_handled": 0,
87+
//! "udp6_announces_handled": 0,
88+
//! "udp6_scrapes_handled": 0
89+
//! }
90+
//! ```
91+
//!
92+
//! # API authentication
93+
//!
94+
//! The API supports authentication using a GET parameter token.
95+
//!
96+
//! <http://0.0.0.0:1212/api/v1/stats?token=MyAccessToken>
97+
//!
98+
//! You can set as many tokens as you want in the configuration file:
99+
//!
100+
//! ```toml
101+
//! [http_api.access_tokens]
102+
//! admin = "MyAccessToken"
103+
//! ```
104+
//!
105+
//! The token label is used to identify the token. All tokens have full access
106+
//! to the API.
107+
//!
108+
//! Refer to [torrust-tracker-configuration](https://docs.rs/torrust-tracker-configuration>)
109+
//! for more information about the API configuration.
110+
//!
111+
//! # Setup SSL (optional)
112+
//!
113+
//! The API server supports SSL. You can enable it by setting the `ssl_enabled`
114+
//! option to `true` in the configuration file.
115+
//!
116+
//! ```toml
117+
//! [http_api]
118+
//! enabled = true
119+
//! bind_address = "0.0.0.0:1212"
120+
//! ssl_enabled = true
121+
//! ssl_cert_path = "./storage/ssl_certificates/localhost.crt"
122+
//! ssl_key_path = "./storage/ssl_certificates/localhost.key"
123+
//!
124+
//! [http_api.access_tokens]
125+
//! admin = "MyAccessToken"
126+
//! ```
127+
//!
128+
//! > **NOTICE**: If you are using a reverse proxy like NGINX, you can skip this
129+
//! step and use NGINX for the SSL instead. See
130+
//! [other alternatives to Nginx/certbot](https://github.com/torrust/torrust-tracker/discussions/131)
131+
//!
132+
//! > **NOTICE**: You can generate a self-signed certificate for localhost using
133+
//! OpenSSL. See [Let's Encrypt](https://letsencrypt.org/docs/certificates-for-localhost/).
134+
//! That's particularly useful for testing purposes. Once you have the certificate
135+
//! you need to set the `ssl_cert_path` and `ssl_key_path` options in the
136+
//! configuration file with the paths to the certificate (`localhost.crt`) and
137+
//! key (`localhost.key`) files.
138+
//!
139+
//! # API endpoints
140+
//!
141+
//! Refer to the [v1](crate::servers::apis::v1) module for the list of available
142+
//! API endpoints.
1143
pub mod routes;
2144
pub mod server;
3145
pub mod v1;
4146

5147
use serde::Deserialize;
6148

149+
/// The info hash URL path parameter.
150+
///
151+
/// Some API endpoints require an info hash as a path parameter.
152+
///
153+
/// For example: `http://localhost:1212/api/v1/torrent/{info_hash}`.
154+
///
155+
/// The info hash represents teh value collected from the URL path parameter.
156+
/// It does not include validation as this is done by the API endpoint handler,
157+
/// in order to provide a more specific error message.
7158
#[derive(Deserialize)]
8159
pub struct InfoHashParam(pub String);

src/servers/apis/routes.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
//! API routes.
2+
//!
3+
//! It loads all the API routes for all API versions and adds the authentication
4+
//! middleware to them.
5+
//!
6+
//! All the API routes have the `/api` prefix and the version number as the
7+
//! first path segment. For example: `/api/v1/torrents`.
18
use std::sync::Arc;
29

310
use axum::{middleware, Router};
@@ -6,6 +13,7 @@ use super::v1;
613
use super::v1::middlewares::auth::auth;
714
use crate::tracker::Tracker;
815

16+
/// Add all API routes to the router.
917
#[allow(clippy::needless_pass_by_value)]
1018
pub fn router(tracker: Arc<Tracker>) -> Router {
1119
let router = Router::new();

src/servers/apis/server.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,28 @@
1+
//! Logic to run the HTTP API server.
2+
//!
3+
//! It contains two main structs: `ApiServer` and `Launcher`,
4+
//! and two main functions: `start` and `start_tls`.
5+
//!
6+
//! The `ApiServer` struct is responsible for:
7+
//! - Starting and stopping the server.
8+
//! - Storing the configuration.
9+
//!
10+
//! `ApiServer` relies on a launcher to start the actual server.
11+
///
12+
/// 1. `ApiServer::start` -> spawns new asynchronous task.
13+
/// 2. `Launcher::start` -> starts the server on the spawned task.
14+
///
15+
/// The `Launcher` struct is responsible for:
16+
///
17+
/// - Knowing how to start the server with graceful shutdown.
18+
///
19+
/// For the time being the `ApiServer` and `Launcher` are only used in tests
20+
/// where we need to start and stop the server multiple times. In production
21+
/// code and the main application uses the `start` and `start_tls` functions
22+
/// to start the servers directly since we do not need to control the server
23+
/// when it's running. In the future we might need to control the server,
24+
/// for example, to restart it to apply new configuration changes, to remotely
25+
/// shutdown the server, etc.
126
use std::net::SocketAddr;
227
use std::str::FromStr;
328
use std::sync::Arc;
@@ -12,24 +37,35 @@ use super::routes::router;
1237
use crate::servers::signals::shutdown_signal;
1338
use crate::tracker::Tracker;
1439

40+
/// Errors that can occur when starting or stopping the API server.
1541
#[derive(Debug)]
1642
pub enum Error {
1743
Error(String),
1844
}
1945

46+
/// An alias for the `ApiServer` struct with the `Stopped` state.
2047
#[allow(clippy::module_name_repetitions)]
2148
pub type StoppedApiServer = ApiServer<Stopped>;
49+
50+
/// An alias for the `ApiServer` struct with the `Running` state.
2251
#[allow(clippy::module_name_repetitions)]
2352
pub type RunningApiServer = ApiServer<Running>;
2453

54+
/// A struct responsible for starting and stopping an API server with a
55+
/// specific configuration and keeping track of the started server.
56+
///
57+
/// It's a state machine that can be in one of two
58+
/// states: `Stopped` or `Running`.
2559
#[allow(clippy::module_name_repetitions)]
2660
pub struct ApiServer<S> {
2761
pub cfg: torrust_tracker_configuration::HttpApi,
2862
pub state: S,
2963
}
3064

65+
/// The `Stopped` state of the `ApiServer` struct.
3166
pub struct Stopped;
3267

68+
/// The `Running` state of the `ApiServer` struct.
3369
pub struct Running {
3470
pub bind_addr: SocketAddr,
3571
task_killer: tokio::sync::oneshot::Sender<u8>,
@@ -42,6 +78,8 @@ impl ApiServer<Stopped> {
4278
Self { cfg, state: Stopped {} }
4379
}
4480

81+
/// Starts the API server with the given configuration.
82+
///
4583
/// # Errors
4684
///
4785
/// It would return an error if no `SocketAddr` is returned after launching the server.
@@ -75,6 +113,8 @@ impl ApiServer<Stopped> {
75113
}
76114

77115
impl ApiServer<Running> {
116+
/// Stops the API server.
117+
///
78118
/// # Errors
79119
///
80120
/// It would return an error if the channel for the task killer signal was closed.
@@ -93,9 +133,15 @@ impl ApiServer<Running> {
93133
}
94134
}
95135

136+
/// A struct responsible for starting the API server.
96137
struct Launcher;
97138

98139
impl Launcher {
140+
/// Starts the API server with graceful shutdown.
141+
///
142+
/// If TLS is enabled in the configuration, it will start the server with
143+
/// TLS. See [torrust-tracker-configuration](https://docs.rs/torrust-tracker-configuration>)
144+
/// for more information about configuration.
99145
pub fn start<F>(
100146
cfg: &torrust_tracker_configuration::HttpApi,
101147
tracker: Arc<Tracker>,
@@ -126,6 +172,7 @@ impl Launcher {
126172
}
127173
}
128174

175+
/// Starts the API server with graceful shutdown.
129176
pub fn start_with_graceful_shutdown<F>(
130177
tcp_listener: std::net::TcpListener,
131178
tracker: Arc<Tracker>,
@@ -146,6 +193,7 @@ impl Launcher {
146193
})
147194
}
148195

196+
/// Starts the API server with graceful shutdown and TLS.
149197
pub fn start_tls_with_graceful_shutdown<F>(
150198
tcp_listener: std::net::TcpListener,
151199
(ssl_cert_path, ssl_key_path): (String, String),
@@ -180,6 +228,7 @@ impl Launcher {
180228
}
181229
}
182230

231+
/// Starts the API server with graceful shutdown on the current thread.
183232
pub fn start(socket_addr: SocketAddr, tracker: Arc<Tracker>) -> impl Future<Output = hyper::Result<()>> {
184233
let app = router(tracker);
185234

@@ -191,6 +240,7 @@ pub fn start(socket_addr: SocketAddr, tracker: Arc<Tracker>) -> impl Future<Outp
191240
})
192241
}
193242

243+
/// Starts the API server with graceful shutdown and TLS on the current thread.
194244
pub fn start_tls(
195245
socket_addr: SocketAddr,
196246
ssl_config: RustlsConfig,

src/servers/apis/v1/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//! The API version `1`.
12
pub mod context;
23
pub mod middlewares;
34
pub mod responses;

src/servers/http/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//! Tracker HTTP/HTTPS Protocol:
1+
//! Tracker HTTP/HTTPS Protocol.
22
//!
33
//! Original specification in BEP 3 (section "Trackers"):
44
//!

src/tracker/mod.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@
7979
//!
8080
//! let peer_ip = IpAddr::V4(Ipv4Addr::from_str("126.0.0.1").unwrap());
8181
//! ```
82-
//! ```rust,ignore
82+
//!
83+
//! ```text
8384
//! let announce_data = tracker.announce(&info_hash, &mut peer, &peer_ip).await;
8485
//! ```
8586
//!
@@ -412,7 +413,7 @@
412413
//!
413414
//! For example, the HTTP tracker would send an event like the following when it handles an `announce` request received from a peer using IP version 4.
414415
//!
415-
//! ```rust,ignore
416+
//! ```text
416417
//! tracker.send_stats_event(statistics::Event::Tcp4Announce).await
417418
//! ```
418419
//!

src/tracker/services/statistics/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
//! - An statistics [`EventSender`](crate::tracker::statistics::EventSender)
1313
//! - An statistics [`Repo`](crate::tracker::statistics::Repo)
1414
//!
15-
//! ```rust,ignore
15+
//! ```text
1616
//! let (stats_event_sender, stats_repository) = factory(tracker_usage_statistics);
1717
//! ```
1818
//!
@@ -23,7 +23,7 @@
2323
//!
2424
//! For example, if you send the event [`Event::Udp4Connect`](crate::tracker::statistics::Event::Udp4Connect):
2525
//!
26-
//! ```rust,ignore
26+
//! ```text
2727
//! let result = event_sender.send_event(Event::Udp4Connect).await;
2828
//! ```
2929
//!

0 commit comments

Comments
 (0)