You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
98 lines
2.6 KiB
98 lines
2.6 KiB
mod configs; |
|
mod error; |
|
mod handlers; |
|
mod models; |
|
mod repo; |
|
|
|
use std::{fs, sync::Arc}; |
|
|
|
use axum::{routing::get, Router}; |
|
use configs::Config; |
|
use error::{AppError, AppResult}; |
|
use models::AppState; |
|
use reqwest::Url; |
|
use tokio::{net::TcpListener, sync::RwLock}; |
|
|
|
#[macro_use] |
|
extern crate log; |
|
|
|
/// Parse urls and return 2 lists: valid urls and errors |
|
fn parse_urls(url_list: &[String]) -> (Vec<Url>, Vec<String>) { |
|
let (valid, invalid): (Vec<_>, Vec<_>) = url_list |
|
.into_iter() |
|
.map(|url| Url::parse(&url).map_err(|e| AppError::InvalidUrl(url.to_string(), e))) |
|
.partition(Result::is_ok); |
|
|
|
( |
|
valid.into_iter().map(Result::unwrap).collect(), |
|
invalid |
|
.into_iter() |
|
.map(|e| e.unwrap_err().to_string()) |
|
.collect(), |
|
) |
|
} |
|
|
|
/// Extract raw urls from different sources: |
|
/// - from args list |
|
/// - from file |
|
fn parse_urls_from_args( |
|
args: impl IntoIterator<Item = String>, |
|
) -> AppResult<(Vec<Url>, Vec<String>)> { |
|
let mut args_iter = args.into_iter(); |
|
|
|
match args_iter.nth(1) { |
|
Some(action) => match action.as_str() { |
|
"-f" => { |
|
let Some(source) = args_iter.next() else { |
|
return Err(AppError::UsageError); |
|
}; |
|
println!("Reading file '{source}'"); |
|
let raw_urls = fs::read_to_string(source)? |
|
.split('\n') |
|
.map(|s| s.to_owned()) |
|
.collect::<Vec<_>>(); |
|
|
|
Ok(parse_urls(&raw_urls)) |
|
} |
|
"-u" => { |
|
let urls_list = args_iter.collect::<Vec<_>>(); |
|
Ok(parse_urls(&urls_list)) |
|
} |
|
_ => return Err(AppError::UsageError), |
|
}, |
|
None => return Err(AppError::UsageError), |
|
} |
|
} |
|
|
|
async fn process_urls(config: &Config, urls: &[Url]) {} |
|
|
|
async fn run() -> AppResult<()> { |
|
dotenv::dotenv().ok(); |
|
|
|
let cfg = configs::get_configs()?; |
|
info!("{cfg:?}"); |
|
|
|
// let (valid_urls, errors) = parse_urls_from_args(args)?; |
|
let state = Arc::new(RwLock::new(AppState::new(cfg.url_handlers_pool_size))); |
|
|
|
let app = Router::new() |
|
.route( |
|
"/urls", |
|
get(handlers::get_urls) |
|
.post(handlers::upload_urls) |
|
.delete(handlers::delete_urls), |
|
) |
|
.with_state(state); |
|
let listener = TcpListener::bind("0.0.0.0:8000").await?; |
|
|
|
axum::serve(listener, app).await.map_err(AppError::from) |
|
} |
|
|
|
#[tokio::main] |
|
async fn main() { |
|
env_logger::init(); |
|
|
|
if let Err(e) = run().await { |
|
println!("{e}"); |
|
} |
|
}
|
|
|