various: shared HTTP client with connection pooling
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Id13c17e9352da970a289f4e3ad909c5b6a6a6964
This commit is contained in:
parent
0cc72e9916
commit
7ee9ee1159
6 changed files with 64 additions and 20 deletions
16
src/http.rs
Normal file
16
src/http.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use reqwest::Client;
|
||||||
|
|
||||||
|
pub fn create_http_client() -> Client {
|
||||||
|
Client::builder()
|
||||||
|
.pool_max_idle_per_host(10)
|
||||||
|
.pool_idle_timeout(Duration::from_secs(30))
|
||||||
|
.tcp_keepalive(Duration::from_secs(60))
|
||||||
|
.tcp_nodelay(true)
|
||||||
|
.connect_timeout(Duration::from_secs(15))
|
||||||
|
.timeout(Duration::from_secs(30))
|
||||||
|
.user_agent("Pakker/0.1.0")
|
||||||
|
.build()
|
||||||
|
.expect("Failed to build HTTP client")
|
||||||
|
}
|
||||||
|
|
@ -9,6 +9,7 @@ mod error;
|
||||||
mod export;
|
mod export;
|
||||||
mod fetch;
|
mod fetch;
|
||||||
mod git;
|
mod git;
|
||||||
|
mod http;
|
||||||
mod ipc;
|
mod ipc;
|
||||||
mod model;
|
mod model;
|
||||||
mod platform;
|
mod platform;
|
||||||
|
|
@ -23,8 +24,6 @@ use clap::Parser;
|
||||||
use cli::{Cli, Commands};
|
use cli::{Cli, Commands};
|
||||||
use error::PakkerError;
|
use error::PakkerError;
|
||||||
|
|
||||||
use crate::rate_limiter::RateLimiter;
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), PakkerError> {
|
async fn main() -> Result<(), PakkerError> {
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
|
|
@ -48,8 +47,6 @@ async fn main() -> Result<(), PakkerError> {
|
||||||
let lockfile_path = working_dir.join("pakker-lock.json");
|
let lockfile_path = working_dir.join("pakker-lock.json");
|
||||||
let config_path = working_dir.join("pakker.json");
|
let config_path = working_dir.join("pakker.json");
|
||||||
|
|
||||||
let _rate_limiter = std::sync::Arc::new(RateLimiter::new(None));
|
|
||||||
|
|
||||||
match cli.command {
|
match cli.command {
|
||||||
Commands::Init(args) => {
|
Commands::Init(args) => {
|
||||||
cli::commands::init::execute(args, &lockfile_path, &config_path).await
|
cli::commands::init::execute(args, &lockfile_path, &config_path).await
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,18 @@ pub use github::GitHubPlatform;
|
||||||
pub use modrinth::ModrinthPlatform;
|
pub use modrinth::ModrinthPlatform;
|
||||||
pub use traits::PlatformClient;
|
pub use traits::PlatformClient;
|
||||||
|
|
||||||
use crate::{error::Result, rate_limiter::RateLimiter};
|
use crate::{error::Result, http, rate_limiter::RateLimiter};
|
||||||
|
|
||||||
|
static HTTP_CLIENT: std::sync::LazyLock<Arc<reqwest::Client>> =
|
||||||
|
std::sync::LazyLock::new(|| Arc::new(http::create_http_client()));
|
||||||
|
|
||||||
static RATE_LIMITER: std::sync::LazyLock<Arc<RateLimiter>> =
|
static RATE_LIMITER: std::sync::LazyLock<Arc<RateLimiter>> =
|
||||||
std::sync::LazyLock::new(|| Arc::new(RateLimiter::new(None)));
|
std::sync::LazyLock::new(|| Arc::new(RateLimiter::new(None)));
|
||||||
|
|
||||||
|
pub fn get_http_client() -> Arc<reqwest::Client> {
|
||||||
|
HTTP_CLIENT.clone()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_platform(
|
pub fn create_platform(
|
||||||
platform: &str,
|
platform: &str,
|
||||||
api_key: Option<String>,
|
api_key: Option<String>,
|
||||||
|
|
@ -33,9 +40,21 @@ fn create_client(
|
||||||
api_key: Option<String>,
|
api_key: Option<String>,
|
||||||
) -> Result<Box<dyn PlatformClient>> {
|
) -> Result<Box<dyn PlatformClient>> {
|
||||||
match platform {
|
match platform {
|
||||||
"modrinth" => Ok(Box::new(ModrinthPlatform::new())),
|
"modrinth" => {
|
||||||
"curseforge" => Ok(Box::new(CurseForgePlatform::new(api_key))),
|
Ok(Box::new(ModrinthPlatform::with_client(get_http_client())))
|
||||||
"github" => Ok(Box::new(GitHubPlatform::new(api_key))),
|
},
|
||||||
|
"curseforge" => {
|
||||||
|
Ok(Box::new(CurseForgePlatform::with_client(
|
||||||
|
get_http_client(),
|
||||||
|
api_key,
|
||||||
|
)))
|
||||||
|
},
|
||||||
|
"github" => {
|
||||||
|
Ok(Box::new(GitHubPlatform::with_client(
|
||||||
|
get_http_client(),
|
||||||
|
api_key,
|
||||||
|
)))
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
Err(crate::error::PakkerError::ConfigError(format!(
|
Err(crate::error::PakkerError::ConfigError(format!(
|
||||||
"Unknown platform: {platform}"
|
"Unknown platform: {platform}"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
|
|
@ -20,18 +20,22 @@ const LOADER_VERSION_TYPE_ID: i32 = 68441;
|
||||||
const DEPENDENCY_RELATION_TYPE_REQUIRED: u32 = 3;
|
const DEPENDENCY_RELATION_TYPE_REQUIRED: u32 = 3;
|
||||||
|
|
||||||
pub struct CurseForgePlatform {
|
pub struct CurseForgePlatform {
|
||||||
client: Client,
|
client: Arc<Client>,
|
||||||
api_key: Option<String>,
|
api_key: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CurseForgePlatform {
|
impl CurseForgePlatform {
|
||||||
pub fn new(api_key: Option<String>) -> Self {
|
pub fn new(api_key: Option<String>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
client: Client::new(),
|
client: Arc::new(Client::new()),
|
||||||
api_key,
|
api_key,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_client(client: Arc<Client>, api_key: Option<String>) -> Self {
|
||||||
|
Self { client, api_key }
|
||||||
|
}
|
||||||
|
|
||||||
fn get_headers(&self) -> Result<reqwest::header::HeaderMap> {
|
fn get_headers(&self) -> Result<reqwest::header::HeaderMap> {
|
||||||
let mut headers = reqwest::header::HeaderMap::new();
|
let mut headers = reqwest::header::HeaderMap::new();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
@ -20,9 +20,9 @@ pub struct GitHubPlatform {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GitHubPlatform {
|
impl GitHubPlatform {
|
||||||
pub fn new(token: Option<String>) -> Self {
|
pub fn with_client(client: Arc<Client>, token: Option<String>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
client: Client::new(),
|
client: (*client).clone(),
|
||||||
token,
|
token,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, sync::Arc};
|
||||||
|
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
|
|
@ -14,16 +14,20 @@ use crate::{
|
||||||
const MODRINTH_API_BASE: &str = "https://api.modrinth.com/v2";
|
const MODRINTH_API_BASE: &str = "https://api.modrinth.com/v2";
|
||||||
|
|
||||||
pub struct ModrinthPlatform {
|
pub struct ModrinthPlatform {
|
||||||
client: Client,
|
client: Arc<Client>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModrinthPlatform {
|
impl ModrinthPlatform {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
client: Client::new(),
|
client: Arc::new(Client::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_client(client: Arc<Client>) -> Self {
|
||||||
|
Self { client }
|
||||||
|
}
|
||||||
|
|
||||||
async fn request_project_url(&self, url: &str) -> Result<Project> {
|
async fn request_project_url(&self, url: &str) -> Result<Project> {
|
||||||
let response = self.client.get(url).send().await?;
|
let response = self.client.get(url).send().await?;
|
||||||
if !response.status().is_success() {
|
if !response.status().is_success() {
|
||||||
|
|
@ -295,13 +299,17 @@ struct ModrinthDependency {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
impl ModrinthPlatform {
|
impl ModrinthPlatform {
|
||||||
fn with_client(client: Client) -> Self {
|
fn with_raw_client(client: Client) -> Self {
|
||||||
Self { client }
|
Self {
|
||||||
|
client: Arc::new(client),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -309,7 +317,7 @@ mod tests {
|
||||||
-> (ModrinthPlatform, mockito::ServerGuard) {
|
-> (ModrinthPlatform, mockito::ServerGuard) {
|
||||||
let server = mockito::Server::new_async().await;
|
let server = mockito::Server::new_async().await;
|
||||||
let client = Client::new();
|
let client = Client::new();
|
||||||
let platform = ModrinthPlatform::with_client(client);
|
let platform = ModrinthPlatform::with_raw_client(client);
|
||||||
(platform, server)
|
(platform, server)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue