117 lines
3.6 KiB
Rust
117 lines
3.6 KiB
Rust
use log::{error, info};
|
|
use rouille::router;
|
|
use rouille::Request;
|
|
use rouille::Response;
|
|
use std::error::Error;
|
|
|
|
use crate::elastic_query::ElasticQuery;
|
|
use crate::options;
|
|
|
|
pub fn serve_request(req: &Request) -> Response {
|
|
router!(req,
|
|
(GET) (/search) => { query(req) },
|
|
_ => Response::empty_404()
|
|
)
|
|
}
|
|
|
|
fn query(req: &Request) -> Response {
|
|
info!("Handling request: {:?}", req);
|
|
let Some(query) = req.get_param("q") else {
|
|
return Response::text("Query Parameter q must be specified!").with_status_code(400);
|
|
};
|
|
match query.len() {
|
|
0..=options::query::MIN_LENGTH => {
|
|
return Response::text(format!(
|
|
"Min query length: {:?}",
|
|
options::query::MIN_LENGTH
|
|
))
|
|
.with_status_code(400);
|
|
}
|
|
options::query::MAX_LENGTH..=usize::MAX => {
|
|
return Response::text(format!(
|
|
"Max query length: {:?}",
|
|
options::query::MAX_LENGTH
|
|
))
|
|
.with_status_code(400);
|
|
}
|
|
_ => (),
|
|
}
|
|
|
|
let response = query_elastic_search(query);
|
|
if let Err(e) = response {
|
|
error!("Error searching: {}", e);
|
|
return Response::text("No fitting awesome list found :(").with_status_code(404);
|
|
}
|
|
let response = response.unwrap();
|
|
|
|
let Some(name) = response.split('.').next() else {
|
|
error!("Error getting name from response!");
|
|
return Response::text("No fitting awesome list found :(").with_status_code(404);
|
|
};
|
|
|
|
info!("Redirecting to: /{}", name);
|
|
Response::redirect_303(format!("/{}", name))
|
|
}
|
|
|
|
fn query_elastic_search(query: String) -> Result<String, Box<dyn Error>> {
|
|
let query = ElasticQuery::new(options::elastic_search::FIELDS.clone(), query);
|
|
|
|
let res = query.send(options::elastic_search::URL.clone())?;
|
|
|
|
Ok(res.hits.hits[0].source.file.file_name.clone())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod test {
|
|
const SEARCH_URL: &str = "/search";
|
|
use super::*;
|
|
mod serve_request {
|
|
use super::*;
|
|
#[test]
|
|
fn test_query_route_exists() {
|
|
let req = Request::fake_http("GET", SEARCH_URL, vec![], vec![]);
|
|
let res = serve_request(&req);
|
|
assert_ne!(res.status_code, 404)
|
|
}
|
|
#[test]
|
|
fn test_non_existant_route() {
|
|
let req = Request::fake_http("GET", "/test", vec![], vec![]);
|
|
let res = serve_request(&req);
|
|
assert_eq!(res.status_code, 404)
|
|
}
|
|
}
|
|
mod query {
|
|
use super::*;
|
|
#[test]
|
|
fn no_query_parameter() {
|
|
let req = Request::fake_http("GET", SEARCH_URL, vec![], vec![]);
|
|
let res = query(&req);
|
|
assert_eq!(res.status_code, 400)
|
|
}
|
|
#[test]
|
|
fn query_too_long() {
|
|
let q: String = std::iter::repeat("a")
|
|
.take(options::query::MAX_LENGTH + 1)
|
|
.collect();
|
|
let req = Request::fake_http("GET", format!("/{}?q={}", SEARCH_URL, q), vec![], vec![]);
|
|
let res = query(&req);
|
|
|
|
let mut body = String::new();
|
|
let _ = res.data.into_reader_and_size().0.read_to_string(&mut body);
|
|
assert_eq!(body, "Max query length: 100");
|
|
assert_eq!(res.status_code, 400)
|
|
}
|
|
#[test]
|
|
fn query_too_short() {
|
|
let req = Request::fake_http("GET", format!("/{}?q=", SEARCH_URL), vec![], vec![]);
|
|
let res = query(&req);
|
|
|
|
assert_eq!(res.status_code, 400);
|
|
|
|
let mut body = String::new();
|
|
let _ = res.data.into_reader_and_size().0.read_to_string(&mut body);
|
|
assert_eq!(body, "Min query length: 3")
|
|
}
|
|
}
|
|
}
|