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

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}");
}
}