Skip to content

Commit

Permalink
docs: [#263] crate docs for apis mod
Browse files Browse the repository at this point in the history
  • Loading branch information
josecelano committed Mar 29, 2023
1 parent 31742c4 commit 2ce17b0
Show file tree
Hide file tree
Showing 29 changed files with 819 additions and 8 deletions.
1 change: 1 addition & 0 deletions cSpell.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"byteorder",
"canonicalize",
"canonicalized",
"certbot",
"chrono",
"clippy",
"completei",
Expand Down
160 changes: 160 additions & 0 deletions src/servers/apis/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,168 @@
//! The tracker REST API with all its versions.
//!
//! > **NOTICE**: This API should not be exposed directly to the internet, it is
//! intended for internal use only.
//!
//! All endpoints require an authorization token which must be set in the
//! configuration before running the tracker. The default configuration uses
//! `?token=MyAccessToken`.
//!
//! Endpoints for the latest API: [v1](crate::servers::apis::v1).
//!
//! # Table of contents
//!
//! - [Configuration](#configuration)
//! - [Authentication](#authentication)
//! - [Versioning](#versioning)
//! - [Endpoints](#endpoints)
//! - [Documentation](#documentation)
//!
//! # Configuration
//!
//! The configuration file has a `http_api` section that can be used to enable
//! the API.
//!
//! ```toml
//! [http_api]
//! enabled = true
//! bind_address = "0.0.0.0:1212"
//! ssl_enabled = false
//! ssl_cert_path = "./storage/ssl_certificates/localhost.crt"
//! ssl_key_path = "./storage/ssl_certificates/localhost.key"
//!
//! [http_api.access_tokens]
//! admin = "MyAccessToken"
//! ```
//!
//! Refer to [torrust-tracker-configuration](https://docs.rs/torrust-tracker-configuration>)
//! for more information about the API configuration.
//!
//! When you run the tracker with enabled API, you will see the following message:
//!
//! ```text
//! Loading configuration from config file ./config.toml
//! 023-03-28T12:19:24.963054069+01:00 [torrust_tracker::bootstrap::logging][INFO] logging initialized.
//! ...
//! 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
//! ```
//!
//! The API server will be available on the address specified in the configuration.
//!
//! You can test the API by loading the following URL on a browser:
//!
//! <http://0.0.0.0:1212/api/v1/stats?token=MyAccessToken>
//!
//! Or using `curl`:
//!
//! ```bash
//! $ curl -s http://0.0.0.0:1212/api/v1/stats?token=MyAccessToken | jq
//! ```
//!
//! The response will be a JSON object. For example, the tracker statistics
//! endpoint:
//!
//! ```json
//! {
//! "torrents": 0,
//! "seeders": 0,
//! "completed": 0,
//! "leechers": 0,
//! "tcp4_connections_handled": 0,
//! "tcp4_announces_handled": 0,
//! "tcp4_scrapes_handled": 0,
//! "tcp6_connections_handled": 0,
//! "tcp6_announces_handled": 0,
//! "tcp6_scrapes_handled": 0,
//! "udp4_connections_handled": 0,
//! "udp4_announces_handled": 0,
//! "udp4_scrapes_handled": 0,
//! "udp6_connections_handled": 0,
//! "udp6_announces_handled": 0,
//! "udp6_scrapes_handled": 0
//! }
//! ```
//!
//! # Authentication
//!
//! The API supports authentication using a GET parameter token.
//!
//! <http://0.0.0.0:1212/api/v1/stats?token=MyAccessToken>
//!
//! You can set as many tokens as you want in the configuration file:
//!
//! ```toml
//! [http_api.access_tokens]
//! admin = "MyAccessToken"
//! ```
//!
//! The token label is used to identify the token. All tokens have full access
//! to the API.
//!
//! Refer to [torrust-tracker-configuration](https://docs.rs/torrust-tracker-configuration>)
//! for more information about the API configuration.
//!
//! # Setup SSL (optional)
//!
//! The API server supports SSL. You can enable it by setting the `ssl_enabled`
//! option to `true` in the configuration file.
//!
//! ```toml
//! [http_api]
//! enabled = true
//! bind_address = "0.0.0.0:1212"
//! ssl_enabled = true
//! ssl_cert_path = "./storage/ssl_certificates/localhost.crt"
//! ssl_key_path = "./storage/ssl_certificates/localhost.key"
//!
//! [http_api.access_tokens]
//! admin = "MyAccessToken"
//! ```
//!
//! > **NOTICE**: If you are using a reverse proxy like NGINX, you can skip this
//! step and use NGINX for the SSL instead. See
//! [other alternatives to Nginx/certbot](https://github.com/torrust/torrust-tracker/discussions/131)
//!
//! > **NOTICE**: You can generate a self-signed certificate for localhost using
//! OpenSSL. See [Let's Encrypt](https://letsencrypt.org/docs/certificates-for-localhost/).
//! That's particularly useful for testing purposes. Once you have the certificate
//! you need to set the `ssl_cert_path` and `ssl_key_path` options in the
//! configuration file with the paths to the certificate (`localhost.crt`) and
//! key (`localhost.key`) files.
//!
//! # Versioning
//!
//! The API is versioned and each version has its own module.
//! The API server runs all the API versions on the same server using
//! the same port. Currently there is only one API version: [v1](crate::servers::apis::v1)
//! but a version [`v2`](https://github.com/torrust/torrust-tracker/issues/144)
//! is planned.
//!
//! # Endpoints
//!git st
//! Refer to the [v1](crate::servers::apis::v1) module for the list of available
//! API endpoints.
//!
//! # Documentation
//!
//! If you want to contribute to this documentation you can [open a new pull request](https://github.com/torrust/torrust-tracker/pulls).
//!
//! > **NOTICE**: we are using [curl](https://curl.se/) in the API examples.
//! And you have to use quotes around the URL in order to avoid unexpected
//! errors.
pub mod routes;
pub mod server;
pub mod v1;

use serde::Deserialize;

/// The info hash URL path parameter.
///
/// Some API endpoints require an info hash as a path parameter.
///
/// For example: `http://localhost:1212/api/v1/torrent/{info_hash}`.
///
/// The info hash represents teh value collected from the URL path parameter.
/// It does not include validation as this is done by the API endpoint handler,
/// in order to provide a more specific error message.
#[derive(Deserialize)]
pub struct InfoHashParam(pub String);
8 changes: 8 additions & 0 deletions src/servers/apis/routes.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
//! API routes.
//!
//! It loads all the API routes for all API versions and adds the authentication
//! middleware to them.
//!
//! All the API routes have the `/api` prefix and the version number as the
//! first path segment. For example: `/api/v1/torrents`.
use std::sync::Arc;

use axum::{middleware, Router};
Expand All @@ -6,6 +13,7 @@ use super::v1;
use super::v1::middlewares::auth::auth;
use crate::tracker::Tracker;

/// Add all API routes to the router.
#[allow(clippy::needless_pass_by_value)]
pub fn router(tracker: Arc<Tracker>) -> Router {
let router = Router::new();
Expand Down
50 changes: 50 additions & 0 deletions src/servers/apis/server.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
//! Logic to run the HTTP API server.
//!
//! It contains two main structs: `ApiServer` and `Launcher`,
//! and two main functions: `start` and `start_tls`.
//!
//! The `ApiServer` struct is responsible for:
//! - Starting and stopping the server.
//! - Storing the configuration.
//!
//! `ApiServer` relies on a launcher to start the actual server.
///
/// 1. `ApiServer::start` -> spawns new asynchronous task.
/// 2. `Launcher::start` -> starts the server on the spawned task.
///
/// The `Launcher` struct is responsible for:
///
/// - Knowing how to start the server with graceful shutdown.
///
/// For the time being the `ApiServer` and `Launcher` are only used in tests
/// where we need to start and stop the server multiple times. In production
/// code and the main application uses the `start` and `start_tls` functions
/// to start the servers directly since we do not need to control the server
/// when it's running. In the future we might need to control the server,
/// for example, to restart it to apply new configuration changes, to remotely
/// shutdown the server, etc.
use std::net::SocketAddr;
use std::str::FromStr;
use std::sync::Arc;
Expand All @@ -12,24 +37,35 @@ use super::routes::router;
use crate::servers::signals::shutdown_signal;
use crate::tracker::Tracker;

/// Errors that can occur when starting or stopping the API server.
#[derive(Debug)]
pub enum Error {
Error(String),
}

/// An alias for the `ApiServer` struct with the `Stopped` state.
#[allow(clippy::module_name_repetitions)]
pub type StoppedApiServer = ApiServer<Stopped>;

/// An alias for the `ApiServer` struct with the `Running` state.
#[allow(clippy::module_name_repetitions)]
pub type RunningApiServer = ApiServer<Running>;

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

/// The `Stopped` state of the `ApiServer` struct.
pub struct Stopped;

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

/// Starts the API server with the given configuration.
///
/// # Errors
///
/// It would return an error if no `SocketAddr` is returned after launching the server.
Expand Down Expand Up @@ -75,6 +113,8 @@ impl ApiServer<Stopped> {
}

impl ApiServer<Running> {
/// Stops the API server.
///
/// # Errors
///
/// It would return an error if the channel for the task killer signal was closed.
Expand All @@ -93,9 +133,15 @@ impl ApiServer<Running> {
}
}

/// A struct responsible for starting the API server.
struct Launcher;

impl Launcher {
/// Starts the API server with graceful shutdown.
///
/// If TLS is enabled in the configuration, it will start the server with
/// TLS. See [torrust-tracker-configuration](https://docs.rs/torrust-tracker-configuration>)
/// for more information about configuration.
pub fn start<F>(
cfg: &torrust_tracker_configuration::HttpApi,
tracker: Arc<Tracker>,
Expand Down Expand Up @@ -126,6 +172,7 @@ impl Launcher {
}
}

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

/// Starts the API server with graceful shutdown and TLS.
pub fn start_tls_with_graceful_shutdown<F>(
tcp_listener: std::net::TcpListener,
(ssl_cert_path, ssl_key_path): (String, String),
Expand Down Expand Up @@ -180,6 +228,7 @@ impl Launcher {
}
}

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

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

/// Starts the API server with graceful shutdown and TLS on the current thread.
pub fn start_tls(
socket_addr: SocketAddr,
ssl_config: RustlsConfig,
Expand Down
Loading

0 comments on commit 2ce17b0

Please sign in to comment.