Skip to content

Commit c4f8f1a

Browse files
committed
feat: Include a swagger UI endpoint
1 parent d19fd21 commit c4f8f1a

4 files changed

Lines changed: 71 additions & 5 deletions

File tree

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ path = "src/main.rs"
2626
rustdoc-args = ["--document-private-items"]
2727

2828
[dependencies]
29+
utoipa = { version = "5.5.0", features = ["actix_extras"] }
30+
utoipa-swagger-ui = { version = "9.0.2", features = ["actix-web"] }
2931
actix-web = "4.13.0"
3032
reqwest = { version = "0.13.3", features = ["blocking", "cookies", "json", "form"] }
3133
serde = { version = "1.0.228", features = ["derive"] }

src/api.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ use uuid::Uuid;
1313
/// # Returns
1414
///
1515
/// Returns the HTTPResponse with a JSON message to indicate the API is up.
16+
#[utoipa::path(
17+
get,
18+
path = "/status",
19+
responses(
20+
(status = 200, description = "List of users", body = serde_json::Value),
21+
),
22+
)]
1623
pub async fn status() -> impl Responder {
1724
HttpResponse::Ok().json(json!({ "status": "ok" }))
1825
}
@@ -22,6 +29,13 @@ pub async fn status() -> impl Responder {
2229
/// # Returns
2330
///
2431
/// Returns the HTTPResponse with a JSON message resolved during compile time.
32+
#[utoipa::path(
33+
get,
34+
path = "/version",
35+
responses(
36+
(status = 200, description = "API version", body = serde_json::Value)
37+
)
38+
)]
2539
pub async fn version() -> impl Responder {
2640
HttpResponse::Ok().json(json!({ "version": env!("CARGO_PKG_VERSION") }))
2741
}
@@ -51,6 +65,13 @@ pub async fn version() -> impl Responder {
5165
/// # Returns
5266
///
5367
/// Returns a JSON object to indicate the status.
68+
#[utoipa::path(
69+
get,
70+
path = "/torrent",
71+
responses(
72+
(status = 200, description = "Torrent status map", body = HashMap<String, String>)
73+
)
74+
)]
5475
pub async fn get_torrents(
5576
state: web::Data<settings::SharedState>,
5677
config: web::Data<settings::Config>,
@@ -220,6 +241,14 @@ fn resolve_payload(body: &[settings::PutItem]) -> Vec<settings::PutItem> {
220241
/// # Returns
221242
///
222243
/// Returns a JSON object to indicate the status.
244+
#[utoipa::path(
245+
put,
246+
path = "/torrent",
247+
request_body = Vec<settings::PutItem>,
248+
responses(
249+
(status = 200, description = "Queued", body = String)
250+
)
251+
)]
223252
pub async fn put_torrent(
224253
pending: web::Data<settings::PendingMap>,
225254
config: web::Data<settings::Config>,
@@ -316,6 +345,17 @@ pub async fn put_torrent(
316345
/// # Returns
317346
///
318347
/// Returns a JSON object to indicate the status.
348+
#[utoipa::path(
349+
delete,
350+
path = "/torrent",
351+
params(
352+
("name" = String, Query, description = "Torrent name"),
353+
("delete-files" = bool, Query, description = "Delete files")
354+
),
355+
responses(
356+
(status = 200, description = "Deleted", body = String)
357+
)
358+
)]
319359
pub async fn delete_torrent(
320360
config: web::Data<settings::Config>,
321361
query: web::Query<HashMap<String, String>>,

src/lib.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
#![allow(rustdoc::bare_urls)]
22
#![doc = include_str!("../README.md")]
33

4-
use actix_web::{web, App, HttpServer};
4+
use actix_web::{web, App, HttpResponse, HttpServer};
55
use std::{collections::HashMap, sync::Arc};
66
use tokio::sync::RwLock;
7+
use utoipa::OpenApi;
8+
use utoipa_swagger_ui::SwaggerUi;
79

810
mod api;
911
mod logger;
@@ -12,6 +14,16 @@ mod rsync;
1214
mod settings;
1315
mod squire;
1416

17+
#[derive(OpenApi)]
18+
#[openapi(paths(
19+
api::status,
20+
api::version,
21+
api::get_torrents,
22+
api::put_torrent,
23+
api::delete_torrent
24+
))]
25+
struct ApiDoc;
26+
1527
/// Contains entrypoint and initializer settings to trigger the asynchronous `HTTPServer`
1628
///
1729
/// # Examples
@@ -44,6 +56,7 @@ pub async fn start() -> std::io::Result<()> {
4456
port,
4557
workers
4658
);
59+
let openapi = ApiDoc::openapi();
4760

4861
HttpServer::new(move || {
4962
App::new()
@@ -56,6 +69,17 @@ pub async fn start() -> std::io::Result<()> {
5669
.route("/torrent", web::get().to(api::get_torrents))
5770
.route("/torrent", web::put().to(api::put_torrent))
5871
.route("/torrent", web::delete().to(api::delete_torrent))
72+
.route(
73+
"/swagger",
74+
web::get().to(|| async {
75+
HttpResponse::Found()
76+
.append_header(("Location", "/swagger-ui/"))
77+
.finish()
78+
}),
79+
)
80+
.service(
81+
SwaggerUi::new("/swagger-ui/{_:.*}").url("/api-docs/openapi.json", openapi.clone()),
82+
)
5983
})
6084
.bind((host, port))?
6185
.workers(workers)

src/settings.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use crate::squire;
2-
use serde::{Deserialize, Serialize};
32
use std::collections::HashMap;
43
use std::num::NonZeroUsize;
54
use std::sync::Arc;
65
use tokio::sync::RwLock;
6+
use utoipa::ToSchema;
77

88
/// ### SharedState
99
/// Shared application state for tracking active rsync operations.
@@ -79,7 +79,7 @@ impl Config {
7979

8080
/// ### Status
8181
/// Represents the current status of a torrent or transfer.
82-
#[derive(Clone, Debug, Serialize)]
82+
#[derive(Clone, Debug, serde::Serialize)]
8383
pub enum Status {
8484
Downloading(f64),
8585
Copying(f64),
@@ -97,7 +97,7 @@ pub struct RsyncTrack {
9797

9898
/// ### RsyncTarget
9999
/// Defines a remote rsync destination.
100-
#[derive(Clone, Debug, Deserialize)]
100+
#[derive(Clone, Debug, serde::Deserialize)]
101101
pub struct RsyncTarget {
102102
pub host: String,
103103
pub username: String,
@@ -106,7 +106,7 @@ pub struct RsyncTarget {
106106

107107
/// ### PutItem
108108
/// Represents an incoming request to add a new torrent with optional rsync target details.
109-
#[derive(Deserialize, Clone, Debug)]
109+
#[derive(ToSchema, Clone, serde::Serialize, serde::Deserialize)]
110110
pub struct PutItem {
111111
pub url: String,
112112

0 commit comments

Comments
 (0)