0
0
mirror of https://github.com/neon-mmd/websurfx.git synced 2024-11-21 21:48:21 -05:00

refactor: moved settings parsing out of results

This commit is contained in:
ddotthomas 2024-01-07 16:29:39 -07:00
parent dde117e7e6
commit 7d762b3726
2 changed files with 68 additions and 105 deletions

View File

@ -2,6 +2,8 @@
//! engine website. //! engine website.
use serde::Deserialize; use serde::Deserialize;
use super::parser_models::Style;
/// A named struct which deserializes all the user provided search parameters and stores them. /// A named struct which deserializes all the user provided search parameters and stores them.
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct SearchParams { pub struct SearchParams {
@ -19,13 +21,26 @@ pub struct SearchParams {
/// A named struct which is used to deserialize the cookies fetched from the client side. /// A named struct which is used to deserialize the cookies fetched from the client side.
#[allow(dead_code)] #[allow(dead_code)]
#[derive(Deserialize)] #[derive(Deserialize)]
pub struct Cookie<'a> { pub struct Cookie {
/// It stores the theme name used in the website. /// It stores the theme name used in the website.
pub theme: &'a str, pub theme: String,
/// It stores the colorscheme name used for the website theme. /// It stores the colorscheme name used for the website theme.
pub colorscheme: &'a str, pub colorscheme: String,
/// It stores the user selected upstream search engines selected from the UI. /// It stores the user selected upstream search engines selected from the UI.
pub engines: Vec<&'a str>, pub engines: Vec<String>,
/// It stores the user selected safe search level from the UI. /// It stores the user selected safe search level from the UI.
pub safe_search_level: u8, pub safe_search_level: u8,
} }
impl Cookie {
/// server_models::Cookie contructor function
pub fn build(style: &Style, mut engines: Vec<String>, safe_search_level: u8) -> Self {
engines.sort();
Self {
theme: style.theme.clone(),
colorscheme: style.colorscheme.clone(),
engines,
safe_search_level,
}
}
}

View File

@ -7,7 +7,7 @@ use crate::{
models::{ models::{
aggregation_models::SearchResults, aggregation_models::SearchResults,
engine_models::EngineHandler, engine_models::EngineHandler,
server_models::{Cookie, SearchParams}, server_models::{self, SearchParams},
}, },
results::aggregator::aggregate, results::aggregator::aggregate,
}; };
@ -48,17 +48,37 @@ pub async fn search(
.finish()); .finish());
} }
let get_results = |page| { // Closure to build a server_models::Cookie capturing local references
results( let build_cookie = || {
&config, server_models::Cookie::build(
&cache, &config.style,
query, config
page, .upstream_search_engines
req.clone(), .clone()
&params.safesearch, .into_iter()
.filter_map(|engine_map| engine_map.1.then_some(engine_map.0))
.collect(),
config.safe_search,
) )
}; };
// Get search settings using the user's cookie or from the server's config
let search_settings: server_models::Cookie = match req.cookie("appCookie") {
Some(cookie_value) => {
if let Ok(cookie) = serde_json::from_str(cookie_value.value()) {
cookie
// If there's an issue parsing the cookie's value, default to the config
} else {
build_cookie()
}
}
// If there's no cookie saved, use the server's config
None => build_cookie(),
};
// Closure wrapping the results function capturing local references
let get_results = |page| results(&config, &cache, query, page, &search_settings);
// .max(1) makes sure that the page >= 0. // .max(1) makes sure that the page >= 0.
let page = params.page.unwrap_or(1).max(1) - 1; let page = params.page.unwrap_or(1).max(1) - 1;
@ -105,50 +125,21 @@ async fn results(
cache: &web::Data<SharedCache>, cache: &web::Data<SharedCache>,
query: &str, query: &str,
page: u32, page: u32,
req: HttpRequest, user_settings: &server_models::Cookie,
safe_search: &Option<u8>,
) -> Result<SearchResults, Box<dyn std::error::Error>> { ) -> Result<SearchResults, Box<dyn std::error::Error>> {
// eagerly parse cookie value to evaluate safe search level // eagerly parse cookie value to evaluate safe search level
let cookie_value = req.cookie("appCookie"); let safe_search_level = user_settings.safe_search_level;
let cookie_value: Option<Cookie<'_>> = cookie_value let cache_key = format!(
.as_ref() "http://{}:{}/search?q={}&page={}&safesearch={}&engines={}",
.and_then(|cv| serde_json::from_str(cv.name_value().1).ok()); config.binding_ip,
config.port,
let safe_search_level = get_safesearch_level( query,
safe_search, page,
&cookie_value.as_ref().map(|cv| cv.safe_search_level), safe_search_level,
config.safe_search, user_settings.engines.join(",")
); );
let mut cache_key = format!(
"http://{}:{}/search?q={}&page={}&safesearch={}",
config.binding_ip, config.port, query, page, safe_search_level
);
let mut cookie_engines: Vec<String> = vec![];
let mut config_engines: Vec<String> = config
.upstream_search_engines
.iter()
.filter_map(|(engine, enabled)| enabled.then_some(engine.clone()))
.collect();
config_engines.sort();
// Modify the cache key adding each enabled search engine to the string
if let Some(cookie_value) = &cookie_value {
cookie_engines = cookie_value
.engines
.iter()
.map(|s| String::from(*s))
.collect::<Vec<String>>();
// We sort the list of engine so the cache keys will match between users. The cookie's list of engines is unordered.
cookie_engines.sort();
cache_key = format!("{cache_key}&engines={}", cookie_engines.join(","));
} else {
cache_key = format!("{cache_key}&engines={}", config_engines.join(","));
}
// fetch the cached results json. // fetch the cached results json.
let cached_results = cache.cached_results(&cache_key).await; let cached_results = cache.cached_results(&cache_key).await;
// check if fetched cache results was indeed fetched or it was an error and if so // check if fetched cache results was indeed fetched or it was an error and if so
@ -174,23 +165,19 @@ async fn results(
// default selected upstream search engines from the config file otherwise // default selected upstream search engines from the config file otherwise
// parse the non-empty cookie and grab the user selected engines from the // parse the non-empty cookie and grab the user selected engines from the
// UI and use that. // UI and use that.
let mut results: SearchResults = match cookie_value { let mut results: SearchResults = match user_settings.engines.is_empty() {
// If the cookie was used before
Some(_) => {
// Use the cookie_engines Strings from before to create the EngineHandlers
let engines: Vec<EngineHandler> = cookie_engines
.iter()
.filter_map(|name| EngineHandler::new(name).ok())
.collect();
match engines.is_empty() {
false => { false => {
aggregate( aggregate(
query, query,
page, page,
config.aggregator.random_delay, config.aggregator.random_delay,
config.debug, config.debug,
&engines, &user_settings
.engines
.clone()
.into_iter()
.filter_map(|engine| EngineHandler::new(&engine).ok())
.collect::<Vec<EngineHandler>>(),
config.request_timeout, config.request_timeout,
safe_search_level, safe_search_level,
) )
@ -201,24 +188,6 @@ async fn results(
search_results.set_no_engines_selected(); search_results.set_no_engines_selected();
search_results search_results
} }
}
}
// Otherwise, use the config_engines to create the EngineHandlers
None => {
aggregate(
query,
page,
config.aggregator.random_delay,
config.debug,
&config_engines
.into_iter()
.filter_map(|engine| EngineHandler::new(&engine).ok())
.collect::<Vec<EngineHandler>>(),
config.request_timeout,
safe_search_level,
)
.await?
}
}; };
if results.engine_errors_info().is_empty() if results.engine_errors_info().is_empty()
&& results.results().is_empty() && results.results().is_empty()
@ -259,24 +228,3 @@ fn is_match_from_filter_list(
Ok(false) Ok(false)
} }
/// A helper function which returns the safe search level based on the url params
/// and cookie value.
///
/// # Argurments
///
/// * `safe_search` - Safe search level from the url.
/// * `cookie` - User's cookie
/// * `default` - Safe search level to fall back to
fn get_safesearch_level(safe_search: &Option<u8>, cookie: &Option<u8>, default: u8) -> u8 {
match safe_search {
Some(ss) => {
if *ss >= 3 {
default
} else {
*ss
}
}
None => cookie.unwrap_or(default),
}
}