torrents.csv/server/service/src/main.rs

119 lines
2.7 KiB
Rust
Raw Normal View History

2018-10-11 21:59:30 +00:00
extern crate actix_web;
extern crate serde;
#[macro_use]
extern crate serde_derive;
2018-10-22 18:55:47 +00:00
extern crate grep;
extern crate time;
2018-10-11 21:59:30 +00:00
use actix_web::{fs, fs::NamedFile, http, server, App, HttpRequest, HttpResponse, Query};
2018-10-22 18:55:47 +00:00
use std::error::Error;
use grep::regex::RegexMatcherBuilder;
2018-10-22 18:55:47 +00:00
use grep::searcher::sinks::Lossy;
use grep::searcher::{BinaryDetection, SearcherBuilder};
use std::fs::File;
2018-10-11 21:59:30 +00:00
fn main() {
2018-10-22 18:55:47 +00:00
server::new(|| {
App::new()
.route("/service/search", http::Method::GET, search)
.resource("/favicon.ico", |r| r.f(favicon))
.resource("/", |r| r.f(index))
2018-10-22 18:55:47 +00:00
.handler(
"/static",
2018-10-22 18:55:47 +00:00
fs::StaticFiles::new("../ui/dist/")
.unwrap()
// .index_file("index.html"),
2018-10-22 18:55:47 +00:00
)
.finish()
}).bind("127.0.0.1:8080")
.unwrap()
.run();
2018-10-11 21:59:30 +00:00
}
fn index(_req: &HttpRequest) -> Result<NamedFile, actix_web::error::Error> {
Ok(NamedFile::open("../ui/dist/index.html")?)
}
fn favicon(_req: &HttpRequest) -> Result<NamedFile, actix_web::error::Error> {
Ok(NamedFile::open("../ui/src/favicon.ico")?)
}
2018-10-11 21:59:30 +00:00
#[derive(Deserialize)]
struct SearchQuery {
2018-10-22 18:55:47 +00:00
q: String,
page: Option<usize>,
size: Option<usize>,
2018-10-11 21:59:30 +00:00
}
fn search(query: Query<SearchQuery>) -> HttpResponse {
2018-10-22 18:55:47 +00:00
HttpResponse::Ok()
.header("Access-Control-Allow-Origin", "*")
.content_type("text/csv")
.body(ripgrep(query))
2018-10-11 21:59:30 +00:00
}
fn ripgrep(query: Query<SearchQuery>) -> String {
2018-10-22 18:55:47 +00:00
let page = query.page.unwrap_or(1);
let size = query.size.unwrap_or(10);
let offset = size * (page - 1);
2018-10-22 18:55:47 +00:00
let csv_file = File::open("../../torrents.csv");
println!("query = {} , page = {}, size = {}", query.q, page, size);
2018-10-22 18:55:47 +00:00
let results = search_file(csv_file.unwrap(), &query.q).unwrap();
let last: usize = if offset + size < results.len() {
offset + size
} else {
results.len()
};
results[offset..last].join("")
2018-10-22 18:55:47 +00:00
}
fn search_file(file: File, query: &str) -> Result<Vec<String>, Box<Error>> {
let pattern = query.replace(" ", ".*");
let matcher = RegexMatcherBuilder::new()
.case_insensitive(true)
.build(&pattern)
.unwrap();
2018-10-22 18:55:47 +00:00
let mut matches: Vec<String> = vec![];
let mut searcher = SearcherBuilder::new()
.binary_detection(BinaryDetection::quit(b'\x00'))
// .line_number(false)
.build();
searcher.search_file(
&matcher,
&file,
Lossy(|_lnum, line| {
matches.push(line.to_string());
Ok(true)
}),
)?;
Ok(matches)
}
#[cfg(test)]
mod tests {
use std::fs::File;
use time::PreciseTime;
#[test]
fn test() {
let start = PreciseTime::now();
let results =
super::search_file(File::open("../../torrents.csv").unwrap(), "sherlock").unwrap();
assert!(results.len() > 2);
let end = PreciseTime::now();
println!("Query took {} seconds.", start.to(end));
}
2018-10-11 21:59:30 +00:00
}