Skip to content

Commit 9ff4de4

Browse files
committed
feat: [#472] inject URL scheme in API client
1 parent 2cf5f47 commit 9ff4de4

File tree

4 files changed

+65
-15
lines changed

4 files changed

+65
-15
lines changed

src/console/commands/seeder/app.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
//!
1616
//! ```text
1717
//! cargo run --bin seeder -- \
18-
//! --api-base-url "localhost:3001" \
18+
//! --api-base-url "http://localhost:3001" \
1919
//! --number-of-torrents 1000 \
2020
//! --user admin \
2121
//! --password 12345678 \
@@ -127,12 +127,14 @@
127127
//!
128128
//! As you can see the `info` dictionary is exactly the same, which produces
129129
//! the same info-hash for the torrent.
130+
use std::str::FromStr;
130131
use std::thread::sleep;
131132
use std::time::Duration;
132133

133134
use anyhow::Context;
134135
use clap::Parser;
135136
use log::{debug, info, LevelFilter};
137+
use reqwest::Url;
136138
use text_colorizer::Colorize;
137139
use uuid::Uuid;
138140

@@ -173,9 +175,11 @@ pub async fn run() -> anyhow::Result<()> {
173175

174176
let args = Args::parse();
175177

176-
let api_user = login_index_api(&args.api_base_url, &args.user, &args.password).await;
178+
let api_url = Url::from_str(&args.api_base_url).context("failed to parse API base URL")?;
177179

178-
let api_client = Client::authenticated(&args.api_base_url, &api_user.token);
180+
let api_user = login_index_api(&api_url, &args.user, &args.password).await;
181+
182+
let api_client = Client::authenticated(&api_url, &api_user.token);
179183

180184
info!(target:"seeder", "Uploading { } random torrents to the Torrust Index with a { } seconds interval...", args.number_of_torrents.to_string().yellow(), args.interval.to_string().yellow());
181185

@@ -202,7 +206,7 @@ pub async fn run() -> anyhow::Result<()> {
202206
}
203207

204208
/// It logs in a user in the Index API.
205-
pub async fn login_index_api(api_url: &str, username: &str, password: &str) -> LoggedInUserData {
209+
pub async fn login_index_api(api_url: &Url, username: &str, password: &str) -> LoggedInUserData {
206210
let unauthenticated_client = Client::unauthenticated(api_url);
207211

208212
info!(target:"seeder", "Trying to login with username: {} ...", username.yellow());

src/web/api/client/v1/client.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use reqwest::multipart;
1+
use reqwest::{multipart, Url};
22

33
use super::connection_info::ConnectionInfo;
44
use super::contexts::category::forms::{AddCategoryForm, DeleteCategoryForm};
@@ -22,13 +22,13 @@ impl Client {
2222
}
2323

2424
#[must_use]
25-
pub fn unauthenticated(bind_address: &str) -> Self {
26-
Self::new(ConnectionInfo::anonymous(bind_address, &Self::base_path()))
25+
pub fn unauthenticated(base_url: &Url) -> Self {
26+
Self::new(ConnectionInfo::anonymous(base_url, &Self::base_path()))
2727
}
2828

2929
#[must_use]
30-
pub fn authenticated(bind_address: &str, token: &str) -> Self {
31-
Self::new(ConnectionInfo::new(bind_address, &Self::base_path(), token))
30+
pub fn authenticated(base_url: &Url, token: &str) -> Self {
31+
Self::new(ConnectionInfo::new(base_url, &Self::base_path(), token))
3232
}
3333

3434
#[must_use]

src/web/api/client/v1/connection_info.rs

+50-4
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,70 @@
1+
use std::{fmt, str::FromStr};
2+
3+
use reqwest::Url;
4+
5+
#[derive(Clone)]
6+
pub enum Scheme {
7+
Http,
8+
Https,
9+
}
10+
11+
impl fmt::Display for Scheme {
12+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
13+
match self {
14+
Scheme::Http => write!(f, "http"),
15+
Scheme::Https => write!(f, "https"),
16+
}
17+
}
18+
}
19+
20+
impl FromStr for Scheme {
21+
type Err = ();
22+
23+
fn from_str(s: &str) -> Result<Self, Self::Err> {
24+
match s {
25+
"http" => Ok(Scheme::Http),
26+
"https" => Ok(Scheme::Https),
27+
_ => Err(()),
28+
}
29+
}
30+
}
31+
132
#[derive(Clone)]
233
pub struct ConnectionInfo {
34+
pub scheme: Scheme,
335
pub bind_address: String,
436
pub base_path: String,
537
pub token: Option<String>,
638
}
739

840
impl ConnectionInfo {
41+
/// # Panics
42+
///
43+
/// Will panic if the the base URL does not have a valid scheme: `http` or `https`.
944
#[must_use]
10-
pub fn new(bind_address: &str, base_path: &str, token: &str) -> Self {
45+
pub fn new(base_url: &Url, base_path: &str, token: &str) -> Self {
1146
Self {
12-
bind_address: bind_address.to_string(),
47+
scheme: base_url
48+
.scheme()
49+
.parse()
50+
.expect("base API URL scheme should be 'http' or 'https"),
51+
bind_address: base_url.authority().to_string(),
1352
base_path: base_path.to_string(),
1453
token: Some(token.to_string()),
1554
}
1655
}
1756

57+
/// # Panics
58+
///
59+
/// Will panic if the the base URL does not have a valid scheme: `http` or `https`.
1860
#[must_use]
19-
pub fn anonymous(bind_address: &str, base_path: &str) -> Self {
61+
pub fn anonymous(base_url: &Url, base_path: &str) -> Self {
2062
Self {
21-
bind_address: bind_address.to_string(),
63+
scheme: base_url
64+
.scheme()
65+
.parse()
66+
.expect("base API URL scheme should be 'http' or 'https"),
67+
bind_address: base_url.authority().to_string(),
2268
base_path: base_path.to_string(),
2369
token: None,
2470
}

src/web/api/client/v1/http.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,8 @@ impl Http {
267267

268268
fn base_url(&self, path: &str) -> String {
269269
format!(
270-
"http://{}{}{path}",
271-
&self.connection_info.bind_address, &self.connection_info.base_path
270+
"{}://{}{}{path}",
271+
&self.connection_info.scheme, &self.connection_info.bind_address, &self.connection_info.base_path
272272
)
273273
}
274274
}

0 commit comments

Comments
 (0)