Skip to content

Commit

Permalink
feat: [torrust#472] inject URL scheme in API client
Browse files Browse the repository at this point in the history
  • Loading branch information
josecelano committed Feb 9, 2024
1 parent 2cf5f47 commit 9ff4de4
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 15 deletions.
12 changes: 8 additions & 4 deletions src/console/commands/seeder/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
//!
//! ```text
//! cargo run --bin seeder -- \
//! --api-base-url "localhost:3001" \
//! --api-base-url "http://localhost:3001" \
//! --number-of-torrents 1000 \
//! --user admin \
//! --password 12345678 \
Expand Down Expand Up @@ -127,12 +127,14 @@
//!
//! As you can see the `info` dictionary is exactly the same, which produces
//! the same info-hash for the torrent.
use std::str::FromStr;
use std::thread::sleep;
use std::time::Duration;

use anyhow::Context;
use clap::Parser;
use log::{debug, info, LevelFilter};
use reqwest::Url;
use text_colorizer::Colorize;
use uuid::Uuid;

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

let args = Args::parse();

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

let api_client = Client::authenticated(&args.api_base_url, &api_user.token);
let api_user = login_index_api(&api_url, &args.user, &args.password).await;

let api_client = Client::authenticated(&api_url, &api_user.token);

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());

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

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

info!(target:"seeder", "Trying to login with username: {} ...", username.yellow());
Expand Down
10 changes: 5 additions & 5 deletions src/web/api/client/v1/client.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use reqwest::multipart;
use reqwest::{multipart, Url};

use super::connection_info::ConnectionInfo;
use super::contexts::category::forms::{AddCategoryForm, DeleteCategoryForm};
Expand All @@ -22,13 +22,13 @@ impl Client {
}

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

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

#[must_use]
Expand Down
54 changes: 50 additions & 4 deletions src/web/api/client/v1/connection_info.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,70 @@
use std::{fmt, str::FromStr};

use reqwest::Url;

#[derive(Clone)]
pub enum Scheme {
Http,
Https,
}

impl fmt::Display for Scheme {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Scheme::Http => write!(f, "http"),
Scheme::Https => write!(f, "https"),
}
}
}

impl FromStr for Scheme {
type Err = ();

fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"http" => Ok(Scheme::Http),
"https" => Ok(Scheme::Https),
_ => Err(()),
}
}
}

#[derive(Clone)]
pub struct ConnectionInfo {
pub scheme: Scheme,
pub bind_address: String,
pub base_path: String,
pub token: Option<String>,
}

impl ConnectionInfo {
/// # Panics
///
/// Will panic if the the base URL does not have a valid scheme: `http` or `https`.
#[must_use]
pub fn new(bind_address: &str, base_path: &str, token: &str) -> Self {
pub fn new(base_url: &Url, base_path: &str, token: &str) -> Self {
Self {
bind_address: bind_address.to_string(),
scheme: base_url
.scheme()
.parse()
.expect("base API URL scheme should be 'http' or 'https"),
bind_address: base_url.authority().to_string(),
base_path: base_path.to_string(),
token: Some(token.to_string()),
}
}

/// # Panics
///
/// Will panic if the the base URL does not have a valid scheme: `http` or `https`.
#[must_use]
pub fn anonymous(bind_address: &str, base_path: &str) -> Self {
pub fn anonymous(base_url: &Url, base_path: &str) -> Self {
Self {
bind_address: bind_address.to_string(),
scheme: base_url
.scheme()
.parse()
.expect("base API URL scheme should be 'http' or 'https"),
bind_address: base_url.authority().to_string(),
base_path: base_path.to_string(),
token: None,
}
Expand Down
4 changes: 2 additions & 2 deletions src/web/api/client/v1/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,8 @@ impl Http {

fn base_url(&self, path: &str) -> String {
format!(
"http://{}{}{path}",
&self.connection_info.bind_address, &self.connection_info.base_path
"{}://{}{}{path}",
&self.connection_info.scheme, &self.connection_info.bind_address, &self.connection_info.base_path
)
}
}

0 comments on commit 9ff4de4

Please sign in to comment.