Update
This commit is contained in:
parent
501b9d3093
commit
964534d0d9
21 changed files with 762 additions and 207 deletions
|
@ -1,11 +1,10 @@
|
|||
use actix_web::{get, http, web, HttpResponse};
|
||||
use actix_web_static_files::ResourceFiles;
|
||||
use anyhow::Result;
|
||||
use askama_actix::TemplateToResponse;
|
||||
use diesel::prelude::*;
|
||||
use r2d2_redis::redis;
|
||||
use std::ops::DerefMut;
|
||||
|
||||
use crate::{cache, config, db, markdown};
|
||||
use crate::{cache, db};
|
||||
|
||||
pub mod templates;
|
||||
|
||||
|
@ -24,27 +23,6 @@ async fn not_found() -> HttpResponse {
|
|||
resp
|
||||
}
|
||||
|
||||
#[get("/posts")]
|
||||
async fn posts(db_pool: web::Data<db::DbPool>) -> HttpResponse {
|
||||
let db_conn = &mut match db_pool.get() {
|
||||
Ok(x) => x,
|
||||
Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)),
|
||||
};
|
||||
|
||||
let posts = match db::schema::posts::table
|
||||
.filter(db::schema::posts::active)
|
||||
.order(db::schema::posts::published_at.desc())
|
||||
.load::<db::models::Post>(db_conn)
|
||||
{
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
return HttpResponse::InternalServerError().body(format!("{:?}", e));
|
||||
}
|
||||
};
|
||||
|
||||
templates::Posts { posts }.to_response()
|
||||
}
|
||||
|
||||
#[get("/")]
|
||||
async fn index() -> HttpResponse {
|
||||
templates::Index.to_response()
|
||||
|
@ -55,6 +33,43 @@ async fn about() -> HttpResponse {
|
|||
templates::About.to_response()
|
||||
}
|
||||
|
||||
pub fn get_tags_by_post(id: i32, db_conn: &mut diesel::PgConnection) -> Result<Vec<String>> {
|
||||
Ok(db::schema::tags::table
|
||||
.select(db::schema::tags::name)
|
||||
.filter(
|
||||
db::schema::tags::id.eq_any(
|
||||
db::schema::post_tags::table
|
||||
.select(db::schema::post_tags::tag_id)
|
||||
.filter(db::schema::post_tags::post_id.eq(id))
|
||||
.load::<i32>(db_conn)?,
|
||||
),
|
||||
)
|
||||
.order(db::schema::tags::name)
|
||||
.load::<String>(db_conn)?)
|
||||
}
|
||||
|
||||
#[get("/posts")]
|
||||
async fn posts(
|
||||
db_pool: web::Data<db::DbPool>,
|
||||
redis_pool: web::Data<cache::RedisPool>,
|
||||
) -> HttpResponse {
|
||||
let db_conn = &mut match db_pool.get() {
|
||||
Ok(x) => x,
|
||||
Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)),
|
||||
};
|
||||
let redis_conn = &mut match redis_pool.get() {
|
||||
Ok(x) => x,
|
||||
Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)),
|
||||
};
|
||||
|
||||
let posts = match cache::cache_posts(db_conn, redis_conn) {
|
||||
Ok(x) => x,
|
||||
Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)),
|
||||
};
|
||||
|
||||
templates::Posts { posts }.to_response()
|
||||
}
|
||||
|
||||
#[get("/posts/{slug}")]
|
||||
async fn post_by_slug(
|
||||
db_pool: web::Data<db::DbPool>,
|
||||
|
@ -72,89 +87,181 @@ async fn post_by_slug(
|
|||
Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)),
|
||||
};
|
||||
|
||||
let post_stripped: Option<(i32, String)> = match db::schema::posts::table
|
||||
.select((db::schema::posts::id, db::schema::posts::name))
|
||||
if let Some(post_id) = match db::schema::posts::table
|
||||
.select(db::schema::posts::id)
|
||||
.filter(db::schema::posts::slug.eq(&slug))
|
||||
.filter(db::schema::posts::active)
|
||||
.get_result::<(i32, String)>(db_conn)
|
||||
.first::<i32>(db_conn)
|
||||
.optional()
|
||||
{
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
return HttpResponse::InternalServerError().body(format!("{:?}", e));
|
||||
Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)),
|
||||
} {
|
||||
let post = match cache::cache_post(post_id, db_conn, redis_conn) {
|
||||
Ok(x) => x,
|
||||
Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)),
|
||||
};
|
||||
|
||||
templates::PostBySlug { post }.to_response()
|
||||
} else {
|
||||
let mut resp = templates::StatusCode {
|
||||
status_code: http::StatusCode::NOT_FOUND,
|
||||
message: Some("this post does not exists... yet".to_string()),
|
||||
}
|
||||
.to_response();
|
||||
*resp.status_mut() = http::StatusCode::NOT_FOUND;
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
// let post_stripped: Option<(i32, String, NaiveDate, Option<NaiveDate>)> =
|
||||
// match db::schema::posts::table
|
||||
// .select((
|
||||
// db::schema::posts::id,
|
||||
// db::schema::posts::name,
|
||||
// db::schema::posts::published_at,
|
||||
// db::schema::posts::edited_at,
|
||||
// ))
|
||||
// .filter(db::schema::posts::slug.eq(&slug))
|
||||
// .filter(db::schema::posts::active)
|
||||
// .first::<(i32, String, NaiveDate, Option<NaiveDate>)>(db_conn)
|
||||
// .optional()
|
||||
// {
|
||||
// Ok(x) => x,
|
||||
// Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)),
|
||||
// };
|
||||
//
|
||||
// match post_stripped {
|
||||
// Some(stripped) => {
|
||||
// let (stripped_id, stripped_name, stripped_published_at, stripped_edited_at) = stripped;
|
||||
|
||||
// let key = cache::keys::post_content(stripped_id);
|
||||
|
||||
// match match redis::cmd("GET")
|
||||
// .arg(&key)
|
||||
// .query::<Option<String>>(redis_conn.deref_mut())
|
||||
// {
|
||||
// Ok(x) => x,
|
||||
// Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)),
|
||||
// } {
|
||||
// Some(s) => {
|
||||
// let tags = match get_tags_by_post(stripped_id, db_conn) {
|
||||
// Ok(x) => x,
|
||||
// Err(e) => {
|
||||
// return HttpResponse::InternalServerError().body(format!("{:?}", e))
|
||||
// }
|
||||
// };
|
||||
|
||||
// templates::PostBySlug {
|
||||
// name: stripped_name,
|
||||
// slug,
|
||||
// published_at: stripped_published_at,
|
||||
// edited_at: stripped_edited_at,
|
||||
// tags,
|
||||
// content: s,
|
||||
// }
|
||||
// }
|
||||
// .to_response(),
|
||||
// None => {
|
||||
// let post = match db::schema::posts::table
|
||||
// .filter(db::schema::posts::id.eq(stripped_id))
|
||||
// .first::<db::models::Post>(db_conn)
|
||||
// {
|
||||
// Ok(x) => x,
|
||||
// Err(e) => {
|
||||
// return HttpResponse::InternalServerError().body(format!("{:?}", e))
|
||||
// }
|
||||
// };
|
||||
|
||||
// let html = markdown::to_html(&post.content);
|
||||
|
||||
// match redis::cmd("SET")
|
||||
// .arg(&key)
|
||||
// .arg(&html)
|
||||
// .query::<Option<String>>(redis_conn.deref_mut())
|
||||
// {
|
||||
// Ok(x) => x,
|
||||
// Err(e) => {
|
||||
// return HttpResponse::InternalServerError().body(format!("{:?}", e))
|
||||
// }
|
||||
// };
|
||||
// if let Err(e) = redis::cmd("EXPIRE")
|
||||
// .arg(key)
|
||||
// .arg(config::CONFIG.cache_ttl)
|
||||
// .query::<()>(redis_conn.deref_mut())
|
||||
// {
|
||||
// return HttpResponse::InternalServerError().body(format!("{:?}", e));
|
||||
// }
|
||||
|
||||
// let tags = match get_tags_by_post(stripped_id, db_conn) {
|
||||
// Ok(x) => x,
|
||||
// Err(e) => {
|
||||
// return HttpResponse::InternalServerError().body(format!("{:?}", e))
|
||||
// }
|
||||
// };
|
||||
|
||||
// templates::PostBySlug {
|
||||
// name: post.name,
|
||||
// slug: post.slug,
|
||||
// published_at: stripped_published_at,
|
||||
// edited_at: stripped_edited_at,
|
||||
// tags,
|
||||
// content: html,
|
||||
// }
|
||||
// .to_response()
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// None => {
|
||||
// let mut resp = templates::StatusCode {
|
||||
// status_code: http::StatusCode::NOT_FOUND,
|
||||
// message: Some("this post does not exists... yet".to_string()),
|
||||
// }
|
||||
// .to_response();
|
||||
// *resp.status_mut() = http::StatusCode::NOT_FOUND;
|
||||
|
||||
// resp
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
#[get("/tags/{name}")]
|
||||
async fn tag_by_name(
|
||||
db_pool: web::Data<db::DbPool>,
|
||||
redis_pool: web::Data<cache::RedisPool>,
|
||||
path: web::Path<String>,
|
||||
) -> HttpResponse {
|
||||
const MESSAGE: &str = "this post does not exists... yet";
|
||||
|
||||
let name = path.into_inner();
|
||||
|
||||
let db_conn = &mut match db_pool.get() {
|
||||
Ok(x) => x,
|
||||
Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)),
|
||||
};
|
||||
let redis_conn = &mut match redis_pool.get() {
|
||||
Ok(x) => x,
|
||||
Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)),
|
||||
};
|
||||
|
||||
match post_stripped {
|
||||
Some(stripped) => {
|
||||
let (stripped_id, stripped_name) = stripped;
|
||||
let tag_id = match db::schema::tags::table
|
||||
.select(db::schema::tags::id)
|
||||
.filter(db::schema::tags::name.eq(&name))
|
||||
.first::<i32>(db_conn)
|
||||
{
|
||||
Ok(x) => x,
|
||||
Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)),
|
||||
};
|
||||
let posts_cache = match cache::cache_tag_posts(tag_id, db_conn, redis_conn) {
|
||||
Ok(x) => x,
|
||||
Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)),
|
||||
};
|
||||
|
||||
let key = cache::keys::post_content(stripped_id);
|
||||
|
||||
match match redis::cmd("GET")
|
||||
.arg(&key)
|
||||
.query::<Option<String>>(redis_conn.deref_mut())
|
||||
{
|
||||
Ok(x) => x,
|
||||
Err(e) => return HttpResponse::InternalServerError().body(format!("{:?}", e)),
|
||||
} {
|
||||
Some(s) => templates::PostBySlug {
|
||||
name: stripped_name,
|
||||
slug,
|
||||
content: s,
|
||||
}
|
||||
.to_response(),
|
||||
None => {
|
||||
let post = match db::schema::posts::table
|
||||
.filter(db::schema::posts::id.eq(stripped_id))
|
||||
.first::<db::models::Post>(db_conn)
|
||||
{
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
return HttpResponse::InternalServerError().body(format!("{:?}", e));
|
||||
}
|
||||
};
|
||||
|
||||
let html = markdown::to_html(&post.content);
|
||||
|
||||
match redis::cmd("SET")
|
||||
.arg(&key)
|
||||
.arg(&html)
|
||||
.query::<Option<String>>(redis_conn.deref_mut())
|
||||
{
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
return HttpResponse::InternalServerError().body(format!("{:?}", e))
|
||||
}
|
||||
};
|
||||
if let Err(e) = redis::cmd("EXPIRE")
|
||||
.arg(key)
|
||||
.arg(config::CONFIG.cache_post_content_ttl)
|
||||
.query::<()>(redis_conn.deref_mut())
|
||||
{
|
||||
return HttpResponse::InternalServerError().body(format!("{:?}", e));
|
||||
}
|
||||
|
||||
templates::PostBySlug {
|
||||
name: post.name,
|
||||
slug: post.slug,
|
||||
content: html,
|
||||
}
|
||||
.to_response()
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let mut resp = templates::StatusCode {
|
||||
status_code: http::StatusCode::NOT_FOUND,
|
||||
message: Some("this post does not exists... yet".to_string()),
|
||||
}
|
||||
.to_response();
|
||||
*resp.status_mut() = http::StatusCode::NOT_FOUND;
|
||||
|
||||
resp
|
||||
}
|
||||
templates::TagByName {
|
||||
name,
|
||||
posts: posts_cache,
|
||||
}
|
||||
.to_response()
|
||||
}
|
||||
|
||||
fn setup_routes(cfg: &mut web::ServiceConfig) {
|
||||
|
@ -165,6 +272,7 @@ fn setup_routes(cfg: &mut web::ServiceConfig) {
|
|||
.service(posts)
|
||||
.service(ResourceFiles::new("/static", generated))
|
||||
.service(post_by_slug)
|
||||
.service(tag_by_name)
|
||||
.default_service(web::route().to(not_found));
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue