ddotthomas commited on
Commit
7d762b3
·
1 Parent(s): dde117e

refactor: moved settings parsing out of results

Browse files
src/models/server_models.rs CHANGED
@@ -2,6 +2,8 @@
2
  //! engine website.
3
  use serde::Deserialize;
4
 
 
 
5
  /// A named struct which deserializes all the user provided search parameters and stores them.
6
  #[derive(Deserialize)]
7
  pub struct SearchParams {
@@ -19,13 +21,26 @@ pub struct SearchParams {
19
  /// A named struct which is used to deserialize the cookies fetched from the client side.
20
  #[allow(dead_code)]
21
  #[derive(Deserialize)]
22
- pub struct Cookie<'a> {
23
  /// It stores the theme name used in the website.
24
- pub theme: &'a str,
25
  /// It stores the colorscheme name used for the website theme.
26
- pub colorscheme: &'a str,
27
  /// It stores the user selected upstream search engines selected from the UI.
28
- pub engines: Vec<&'a str>,
29
  /// It stores the user selected safe search level from the UI.
30
  pub safe_search_level: u8,
31
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  //! engine website.
3
  use serde::Deserialize;
4
 
5
+ use super::parser_models::Style;
6
+
7
  /// A named struct which deserializes all the user provided search parameters and stores them.
8
  #[derive(Deserialize)]
9
  pub struct SearchParams {
 
21
  /// A named struct which is used to deserialize the cookies fetched from the client side.
22
  #[allow(dead_code)]
23
  #[derive(Deserialize)]
24
+ pub struct Cookie {
25
  /// It stores the theme name used in the website.
26
+ pub theme: String,
27
  /// It stores the colorscheme name used for the website theme.
28
+ pub colorscheme: String,
29
  /// It stores the user selected upstream search engines selected from the UI.
30
+ pub engines: Vec<String>,
31
  /// It stores the user selected safe search level from the UI.
32
  pub safe_search_level: u8,
33
  }
34
+
35
+ impl Cookie {
36
+ /// server_models::Cookie contructor function
37
+ pub fn build(style: &Style, mut engines: Vec<String>, safe_search_level: u8) -> Self {
38
+ engines.sort();
39
+ Self {
40
+ theme: style.theme.clone(),
41
+ colorscheme: style.colorscheme.clone(),
42
+ engines,
43
+ safe_search_level,
44
+ }
45
+ }
46
+ }
src/server/routes/search.rs CHANGED
@@ -7,7 +7,7 @@ use crate::{
7
  models::{
8
  aggregation_models::SearchResults,
9
  engine_models::EngineHandler,
10
- server_models::{Cookie, SearchParams},
11
  },
12
  results::aggregator::aggregate,
13
  };
@@ -48,17 +48,37 @@ pub async fn search(
48
  .finish());
49
  }
50
 
51
- let get_results = |page| {
52
- results(
53
- &config,
54
- &cache,
55
- query,
56
- page,
57
- req.clone(),
58
- &params.safesearch,
 
 
 
59
  )
60
  };
61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  // .max(1) makes sure that the page >= 0.
63
  let page = params.page.unwrap_or(1).max(1) - 1;
64
 
@@ -105,50 +125,21 @@ async fn results(
105
  cache: &web::Data<SharedCache>,
106
  query: &str,
107
  page: u32,
108
- req: HttpRequest,
109
- safe_search: &Option<u8>,
110
  ) -> Result<SearchResults, Box<dyn std::error::Error>> {
111
  // eagerly parse cookie value to evaluate safe search level
112
- let cookie_value = req.cookie("appCookie");
113
-
114
- let cookie_value: Option<Cookie<'_>> = cookie_value
115
- .as_ref()
116
- .and_then(|cv| serde_json::from_str(cv.name_value().1).ok());
117
-
118
- let safe_search_level = get_safesearch_level(
119
- safe_search,
120
- &cookie_value.as_ref().map(|cv| cv.safe_search_level),
121
- config.safe_search,
122
- );
123
-
124
- let mut cache_key = format!(
125
- "http://{}:{}/search?q={}&page={}&safesearch={}",
126
- config.binding_ip, config.port, query, page, safe_search_level
127
  );
128
 
129
- let mut cookie_engines: Vec<String> = vec![];
130
- let mut config_engines: Vec<String> = config
131
- .upstream_search_engines
132
- .iter()
133
- .filter_map(|(engine, enabled)| enabled.then_some(engine.clone()))
134
- .collect();
135
- config_engines.sort();
136
-
137
- // Modify the cache key adding each enabled search engine to the string
138
- if let Some(cookie_value) = &cookie_value {
139
- cookie_engines = cookie_value
140
- .engines
141
- .iter()
142
- .map(|s| String::from(*s))
143
- .collect::<Vec<String>>();
144
-
145
- // We sort the list of engine so the cache keys will match between users. The cookie's list of engines is unordered.
146
- cookie_engines.sort();
147
- cache_key = format!("{cache_key}&engines={}", cookie_engines.join(","));
148
- } else {
149
- cache_key = format!("{cache_key}&engines={}", config_engines.join(","));
150
- }
151
-
152
  // fetch the cached results json.
153
  let cached_results = cache.cached_results(&cache_key).await;
154
  // check if fetched cache results was indeed fetched or it was an error and if so
@@ -174,43 +165,16 @@ async fn results(
174
  // default selected upstream search engines from the config file otherwise
175
  // parse the non-empty cookie and grab the user selected engines from the
176
  // UI and use that.
177
- let mut results: SearchResults = match cookie_value {
178
- // If the cookie was used before
179
- Some(_) => {
180
- // Use the cookie_engines Strings from before to create the EngineHandlers
181
- let engines: Vec<EngineHandler> = cookie_engines
182
- .iter()
183
- .filter_map(|name| EngineHandler::new(name).ok())
184
- .collect();
185
-
186
- match engines.is_empty() {
187
- false => {
188
- aggregate(
189
- query,
190
- page,
191
- config.aggregator.random_delay,
192
- config.debug,
193
- &engines,
194
- config.request_timeout,
195
- safe_search_level,
196
- )
197
- .await?
198
- }
199
- true => {
200
- let mut search_results = SearchResults::default();
201
- search_results.set_no_engines_selected();
202
- search_results
203
- }
204
- }
205
- }
206
- // Otherwise, use the config_engines to create the EngineHandlers
207
- None => {
208
  aggregate(
209
  query,
210
  page,
211
  config.aggregator.random_delay,
212
  config.debug,
213
- &config_engines
 
 
214
  .into_iter()
215
  .filter_map(|engine| EngineHandler::new(&engine).ok())
216
  .collect::<Vec<EngineHandler>>(),
@@ -219,6 +183,11 @@ async fn results(
219
  )
220
  .await?
221
  }
 
 
 
 
 
222
  };
223
  if results.engine_errors_info().is_empty()
224
  && results.results().is_empty()
@@ -259,24 +228,3 @@ fn is_match_from_filter_list(
259
 
260
  Ok(false)
261
  }
262
-
263
- /// A helper function which returns the safe search level based on the url params
264
- /// and cookie value.
265
- ///
266
- /// # Argurments
267
- ///
268
- /// * `safe_search` - Safe search level from the url.
269
- /// * `cookie` - User's cookie
270
- /// * `default` - Safe search level to fall back to
271
- fn get_safesearch_level(safe_search: &Option<u8>, cookie: &Option<u8>, default: u8) -> u8 {
272
- match safe_search {
273
- Some(ss) => {
274
- if *ss >= 3 {
275
- default
276
- } else {
277
- *ss
278
- }
279
- }
280
- None => cookie.unwrap_or(default),
281
- }
282
- }
 
7
  models::{
8
  aggregation_models::SearchResults,
9
  engine_models::EngineHandler,
10
+ server_models::{self, SearchParams},
11
  },
12
  results::aggregator::aggregate,
13
  };
 
48
  .finish());
49
  }
50
 
51
+ // Closure to build a server_models::Cookie capturing local references
52
+ let build_cookie = || {
53
+ server_models::Cookie::build(
54
+ &config.style,
55
+ config
56
+ .upstream_search_engines
57
+ .clone()
58
+ .into_iter()
59
+ .filter_map(|engine_map| engine_map.1.then_some(engine_map.0))
60
+ .collect(),
61
+ config.safe_search,
62
  )
63
  };
64
 
65
+ // Get search settings using the user's cookie or from the server's config
66
+ let search_settings: server_models::Cookie = match req.cookie("appCookie") {
67
+ Some(cookie_value) => {
68
+ if let Ok(cookie) = serde_json::from_str(cookie_value.value()) {
69
+ cookie
70
+ // If there's an issue parsing the cookie's value, default to the config
71
+ } else {
72
+ build_cookie()
73
+ }
74
+ }
75
+ // If there's no cookie saved, use the server's config
76
+ None => build_cookie(),
77
+ };
78
+
79
+ // Closure wrapping the results function capturing local references
80
+ let get_results = |page| results(&config, &cache, query, page, &search_settings);
81
+
82
  // .max(1) makes sure that the page >= 0.
83
  let page = params.page.unwrap_or(1).max(1) - 1;
84
 
 
125
  cache: &web::Data<SharedCache>,
126
  query: &str,
127
  page: u32,
128
+ user_settings: &server_models::Cookie,
 
129
  ) -> Result<SearchResults, Box<dyn std::error::Error>> {
130
  // eagerly parse cookie value to evaluate safe search level
131
+ let safe_search_level = user_settings.safe_search_level;
132
+
133
+ let cache_key = format!(
134
+ "http://{}:{}/search?q={}&page={}&safesearch={}&engines={}",
135
+ config.binding_ip,
136
+ config.port,
137
+ query,
138
+ page,
139
+ safe_search_level,
140
+ user_settings.engines.join(",")
 
 
 
 
 
141
  );
142
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  // fetch the cached results json.
144
  let cached_results = cache.cached_results(&cache_key).await;
145
  // check if fetched cache results was indeed fetched or it was an error and if so
 
165
  // default selected upstream search engines from the config file otherwise
166
  // parse the non-empty cookie and grab the user selected engines from the
167
  // UI and use that.
168
+ let mut results: SearchResults = match user_settings.engines.is_empty() {
169
+ false => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  aggregate(
171
  query,
172
  page,
173
  config.aggregator.random_delay,
174
  config.debug,
175
+ &user_settings
176
+ .engines
177
+ .clone()
178
  .into_iter()
179
  .filter_map(|engine| EngineHandler::new(&engine).ok())
180
  .collect::<Vec<EngineHandler>>(),
 
183
  )
184
  .await?
185
  }
186
+ true => {
187
+ let mut search_results = SearchResults::default();
188
+ search_results.set_no_engines_selected();
189
+ search_results
190
+ }
191
  };
192
  if results.engine_errors_info().is_empty()
193
  && results.results().is_empty()
 
228
 
229
  Ok(false)
230
  }