Add web::block to get_comments

main
Elnu 2 years ago
parent cf2779dd40
commit bfb59fbe6f

@ -8,8 +8,8 @@ pub use database::Database;
use actix_web::{get, post, web, App, HttpRequest, HttpResponse, HttpServer, Responder}; use actix_web::{get, post, web, App, HttpRequest, HttpResponse, HttpServer, Responder};
use scraper::{Html, Selector}; use scraper::{Html, Selector};
use serde::Deserialize; use serde::Deserialize;
use std::collections::HashMap; use std::{collections::HashMap, sync::MutexGuard};
use std::sync::{Mutex, MutexGuard}; use std::sync::Mutex;
use validator::Validate; use validator::Validate;
use sanitize_html::{sanitize_str, rules::predefined::DEFAULT, errors::SanitizeError}; use sanitize_html::{sanitize_str, rules::predefined::DEFAULT, errors::SanitizeError};
use clap::Parser; use clap::Parser;
@ -19,6 +19,58 @@ struct AppState {
arguments: Arguments, arguments: Arguments,
} }
enum DatabaseAccessError {
BadOrigin,
AccessError,
DatabaseError
}
impl DatabaseAccessError {
fn to_http_response(&self) -> HttpResponse {
match self {
Self::BadOrigin => HttpResponse::BadRequest().reason("bad origin").finish(),
Self::AccessError => HttpResponse::InternalServerError().reason("database access error").finish(), // e.g. PoisonError
Self::DatabaseError => HttpResponse::InternalServerError().reason("database error").finish(),
}
}
}
impl AppState {
fn get_db<'a>(
&'a self,
request: &HttpRequest,
) -> Result<MutexGuard<'a, Database>, DatabaseAccessError> {
self.get_db_with_origin(get_request_origin(request))
}
fn get_db_with_origin<'a>(
&'a self,
origin: Option<String>,
) -> Result<MutexGuard<'a, Database>, DatabaseAccessError> {
let origin = match origin {
Some(origin) => origin,
None => return Err(DatabaseAccessError::BadOrigin),
};
match self.databases.get(&origin) {
Some(database) => Ok(match database.lock() {
Ok(database) => database,
Err(_) => return Err(DatabaseAccessError::AccessError),
}),
None => return Err(DatabaseAccessError::AccessError),
}
}
}
fn get_request_origin(request: &HttpRequest) -> Option<String> {
match request.head().headers().get("Origin") {
Some(origin) => match origin.to_str() {
Ok(origin) => Some(origin.to_owned()),
Err(_) => None,
},
None => None,
}
}
#[derive(Default, Parser)] #[derive(Default, Parser)]
#[clap(author, version, about)] #[clap(author, version, about)]
struct Arguments { struct Arguments {
@ -34,37 +86,29 @@ struct Arguments {
email_required: bool, email_required: bool,
} }
fn get_db<'a>(
data: &'a web::Data<AppState>,
request: &HttpRequest,
) -> Result<MutexGuard<'a, Database>, HttpResponse> {
let origin = match request.head().headers().get("Origin") {
Some(origin) => match origin.to_str() {
Ok(origin) => origin,
Err(_) => return Err(HttpResponse::BadRequest().reason("bad origin").finish()),
},
None => return Err(HttpResponse::BadRequest().reason("bad origin").finish()),
};
match data.databases.get(origin) {
Some(database) => Ok(match database.lock() {
Ok(database) => database,
Err(_) => return Err(HttpResponse::InternalServerError().reason("database error").finish()),
}),
None => return Err(HttpResponse::BadRequest().reason("bad origin").finish()),
}
}
#[get("/{content_id}")] #[get("/{content_id}")]
async fn get_comments( async fn get_comments(
data: web::Data<AppState>, data: web::Data<AppState>,
request: HttpRequest, request: HttpRequest,
content_id: web::Path<String>, content_id: web::Path<String>,
) -> impl Responder { ) -> impl Responder {
let database = match get_db(&data, &request) { let origin = get_request_origin(&request);
let comments = match web::block(move || {
Ok(match match data.get_db_with_origin(origin) {
Ok(database) => database, Ok(database) => database,
Err(response) => return response, Err(err) => return Err(err),
}.get_comments(&content_id) {
Ok(comments) => comments,
Err(_) => return Err(DatabaseAccessError::DatabaseError),
})
}).await {
Ok(comments) => match comments {
Ok(comments) => comments,
Err(err) => return err.to_http_response(),
},
Err(_) => return DatabaseAccessError::AccessError.to_http_response(),
}; };
HttpResponse::Ok().json(database.get_comments(&content_id).unwrap()) HttpResponse::Ok().json(comments)
} }
#[derive(Deserialize)] #[derive(Deserialize)]
@ -139,9 +183,9 @@ async fn post_comment(
}, },
Err(_) => return HttpResponse::InternalServerError().reason("failed to get page data").finish(), Err(_) => return HttpResponse::InternalServerError().reason("failed to get page data").finish(),
}; };
let database = match get_db(&data, &request) { let database = match data.get_db(&request) {
Ok(database) => database, Ok(database) => database,
Err(response) => return response, Err(err) => return err.to_http_response(),
}; };
if let Some(parent) = comment.parent { if let Some(parent) = comment.parent {
'outer2: loop { 'outer2: loop {

Loading…
Cancel
Save