Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSR for posts and authors #72

Merged
merged 6 commits into from
Dec 25, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion blog-generic/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
pub mod entities;
pub mod events;

const AUTHOR_SLUG_SPLIT_SYMBOL: char = '^';
pub const AUTHOR_SLUG_SPLIT_SYMBOL: char = '^';

pub fn clean_author_slug(slug: &String) -> String {
slug.rsplit_once(AUTHOR_SLUG_SPLIT_SYMBOL)
Expand All @@ -12,3 +12,13 @@ pub fn clean_author_slug(slug: &String) -> String {
pub fn extend_author_slug(slug: &String, suffix: &String) -> String {
format!("{slug}{AUTHOR_SLUG_SPLIT_SYMBOL}{suffix}")
}

pub const ITEMS_PER_PAGE: u64 = 10;

pub fn offset_for_page<const LIMIT: u64>(page: &u64) -> u64 {
let Some(real_page) = page.checked_sub(1) else {
return 0;
};
let offset = real_page * LIMIT;
offset
}
18 changes: 18 additions & 0 deletions blog-server-api/src/endpoints/author/handler.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
use std::sync::Arc;

use blog_generic::entities::AuthorContainer;
use blog_server_services::traits::author_service::AuthorService;

use super::request_content::AuthorRequestContent;
use super::response_content_failure::AuthorResponseContentFailure;
use super::response_content_failure::AuthorResponseContentFailure::*;
Expand All @@ -23,3 +28,16 @@ pub async fn http_handler(

Ok(author.into())
}

pub async fn direct_handler(
slug: String,
author_service: Arc<Box<dyn AuthorService>>,
) -> Option<AuthorContainer> {
http_handler((AuthorRequestContent {
slug,
author_service,
},))
.await
.ok()
.map(|s| s.container)
}
3 changes: 0 additions & 3 deletions blog-server-api/src/endpoints/author/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,3 @@ mod response_content_failure;
mod response_content_success;

pub use handler::*;
pub use request_content::*;
pub use response_content_failure::*;
pub use response_content_success::*;
4 changes: 2 additions & 2 deletions blog-server-api/src/endpoints/author/request_content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use screw_api::request::{ApiRequestContent, ApiRequestOriginContent};
use std::sync::Arc;

pub struct AuthorRequestContent {
pub slug: String,
pub author_service: Arc<Box<dyn AuthorService>>,
pub(super) slug: String,
pub(super) author_service: Arc<Box<dyn AuthorService>>,
}

impl<Extensions> ApiRequestContent<Extensions> for AuthorRequestContent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use screw_api::response::{ApiResponseContentBase, ApiResponseContentSuccess};

#[derive(Debug, Clone)]
pub struct AuthorResponseContentSuccess {
pub container: AuthorContainer,
pub(super) container: AuthorContainer,
}

impl Into<AuthorResponseContentSuccess> for ServiceAuthor {
Expand Down
19 changes: 19 additions & 0 deletions blog-server-api/src/endpoints/authors/handler.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use std::sync::Arc;

use blog_generic::entities::{AuthorsContainer, TotalOffsetLimitContainer};
use blog_server_services::traits::author_service::AuthorService;

use super::request_content::AuthorsRequestContent;
use super::response_content_failure::AuthorsResponseContentFailure;
Expand Down Expand Up @@ -50,3 +53,19 @@ pub async fn http_handler(
}
.into())
}

pub async fn direct_handler(
offset: u64,
limit: u64,
author_service: Arc<Box<dyn AuthorService>>,
) -> Option<AuthorsContainer> {
http_handler((AuthorsRequestContent {
query: None,
offset: Some(offset),
limit: Some(limit),
author_service,
},))
.await
.ok()
.map(|s| s.container)
}
2 changes: 1 addition & 1 deletion blog-server-api/src/endpoints/authors/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ mod request_content;
mod response_content_failure;
mod response_content_success;

pub use handler::http_handler;
pub use handler::*;
97 changes: 43 additions & 54 deletions blog-server-api/src/endpoints/client_handler.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::endpoints::*;
use crate::extensions::Resolve;
use crate::utils::auth;
use blog_server_services::traits::author_service::*;
use blog_server_services::traits::entity_post_service::*;
use blog_server_services::traits::post_service::*;
Expand All @@ -8,6 +8,7 @@ use screw_core::request::*;
use screw_core::response::*;
use screw_core::routing::*;

use blog_generic::*;
use blog_ui::*;

const INDEX_HTML: &str = include_str!("../../../index.html");
Expand Down Expand Up @@ -164,6 +165,7 @@ async fn status<Extensions>(
}
}

// TODO: to think, if it's not a cringe
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kind of)00

async fn app_content<Extensions>(
request: &router::RoutedRequest<Request<Extensions>>,
) -> Option<AppContent>
Expand All @@ -172,63 +174,50 @@ where
+ Resolve<std::sync::Arc<Box<dyn PostService>>>
+ Resolve<std::sync::Arc<Box<dyn EntityPostService>>>,
{
let offset = || -> u64 {
offset_for_page::<ITEMS_PER_PAGE>(
&request
.query
.get("page")
.map(|v| v.parse().ok())
.flatten()
.unwrap_or(1),
)
};
let limit = || -> u64 { ITEMS_PER_PAGE };
match Route::recognize_path(request.path.as_str())? {
Route::Post { slug: _, id } | Route::EditPost { id } => {
use crate::endpoints::post;
let post_service: std::sync::Arc<Box<dyn PostService>> =
request.origin.extensions.resolve();
let entity_post_service: std::sync::Arc<Box<dyn EntityPostService>> =
request.origin.extensions.resolve();

let Ok(post::PostResponseContentSuccess { container }) =
post::http_handler((post::PostRequestContent {
id: id.to_string(),
post_service,
entity_post_service,
auth_author_future: Box::pin(std::future::ready(Err(
auth::Error::TokenMissing,
))),
},))
.await
else {
return None;
};

app_content_encode(&container.post)
}
Route::Author { slug } => {
use crate::endpoints::author;
let author_service: std::sync::Arc<Box<dyn AuthorService>> =
request.origin.extensions.resolve();

let Ok(author::AuthorResponseContentSuccess { container }) =
author::http_handler((author::AuthorRequestContent {
slug,
author_service,
},))
Route::Post { slug: _, id } | Route::EditPost { id } => post::direct_handler(
id.to_string(),
request.origin.extensions.resolve(),
request.origin.extensions.resolve(),
)
.await
.map(|v| app_content_encode(&v.post))
.flatten(),
Route::Author { slug } => author::direct_handler(slug, request.origin.extensions.resolve())
.await
.map(|v| app_content_encode(&v.author))
.flatten(),
Route::Tag { slug: _, id } => {
tag::direct_handler(id.to_string(), request.origin.extensions.resolve())
.await
else {
return None;
};

app_content_encode(&container.author)
.map(|v| app_content_encode(&v.tag))
.flatten()
}
Route::Tag { slug: _, id } => {
use crate::endpoints::tag;
let post_service: std::sync::Arc<Box<dyn PostService>> =
request.origin.extensions.resolve();

let Ok(tag::TagResponseContentSuccess { container }) =
tag::http_handler((tag::TagRequestContent {
id: id.to_string(),
post_service,
},))
Route::Posts => posts::direct_handler(
offset(),
limit(),
request.origin.extensions.resolve(),
request.origin.extensions.resolve(),
)
.await
.map(|v| app_content_encode(&v))
.flatten(),
Route::Authors => {
authors::direct_handler(offset(), limit(), request.origin.extensions.resolve())
.await
else {
return None;
};

app_content_encode(&container.tag)
.map(|v| app_content_encode(&v))
.flatten()
}
_ => None,
}
Expand Down
24 changes: 24 additions & 0 deletions blog-server-api/src/endpoints/post/handler.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
use std::sync::Arc;

use blog_generic::entities::PostContainer;
use blog_server_services::traits::entity_post_service::EntityPostService;
use blog_server_services::traits::post_service::PostService;

use crate::utils::auth;

use super::request_content::PostRequestContent;
use super::response_content_failure::PostResponseContentFailure;
use super::response_content_failure::PostResponseContentFailure::*;
Expand Down Expand Up @@ -44,3 +52,19 @@ pub async fn http_handler(

Ok(post_entity.into())
}

pub async fn direct_handler(
id: String,
post_service: Arc<Box<dyn PostService>>,
entity_post_service: Arc<Box<dyn EntityPostService>>,
) -> Option<PostContainer> {
http_handler((PostRequestContent {
id,
post_service,
entity_post_service,
auth_author_future: Box::pin(std::future::ready(Err(auth::Error::TokenMissing))),
},))
.await
.ok()
.map(|s| s.container)
}
3 changes: 0 additions & 3 deletions blog-server-api/src/endpoints/post/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,3 @@ mod response_content_failure;
mod response_content_success;

pub use handler::*;
pub use request_content::*;
pub use response_content_failure::*;
pub use response_content_success::*;
8 changes: 4 additions & 4 deletions blog-server-api/src/endpoints/post/request_content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ use screw_components::dyn_fn::DFuture;
use std::sync::Arc;

pub struct PostRequestContent {
pub id: String,
pub post_service: Arc<Box<dyn PostService>>,
pub entity_post_service: Arc<Box<dyn EntityPostService>>,
pub auth_author_future: DFuture<Result<Author, auth::Error>>,
pub(super) id: String,
pub(super) post_service: Arc<Box<dyn PostService>>,
pub(super) entity_post_service: Arc<Box<dyn EntityPostService>>,
pub(super) auth_author_future: DFuture<Result<Author, auth::Error>>,
}

impl<Extensions> ApiRequestContent<Extensions> for PostRequestContent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use screw_api::response::{ApiResponseContentBase, ApiResponseContentSuccess};

#[derive(Debug, Clone)]
pub struct PostResponseContentSuccess {
pub container: PostContainer,
pub(super) container: PostContainer,
}

impl Into<PostResponseContentSuccess> for Post {
Expand Down
22 changes: 22 additions & 0 deletions blog-server-api/src/endpoints/posts/handler.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
use std::sync::Arc;

use crate::utils::auth;
use blog_generic::entities::{PostsContainer, TotalOffsetLimitContainer};
use blog_server_services::traits::author_service::Author;
use blog_server_services::traits::entity_post_service::EntityPostService;
use blog_server_services::traits::post_service::PostService;
use screw_components::dyn_fn::DFuture;

use super::request_content::{PostsRequestContentFilter as Filter, *};
Expand Down Expand Up @@ -124,3 +128,21 @@ async fn handler(
}
.into())
}

pub async fn direct_handler(
offset: u64,
limit: u64,
post_service: Arc<Box<dyn PostService>>,
entity_post_service: Arc<Box<dyn EntityPostService>>,
) -> Option<PostsContainer> {
http_handler((PostsRequestContent {
filter: None,
offset: Some(offset),
limit: Some(limit),
post_service,
entity_post_service,
},))
.await
.ok()
.map(|s| s.container)
}
2 changes: 1 addition & 1 deletion blog-server-api/src/endpoints/posts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ mod request_content;
mod response_content_failure;
mod response_content_success;

pub use handler::{http_handler, http_handler_unpublished};
pub use handler::*;
15 changes: 15 additions & 0 deletions blog-server-api/src/endpoints/tag/handler.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
use std::sync::Arc;

use blog_generic::entities::TagContainer;
use blog_server_services::traits::post_service::PostService;

use super::request_content::TagRequestContent;
use super::response_content_failure::TagResponseContentFailure;
use super::response_content_failure::TagResponseContentFailure::*;
Expand All @@ -20,3 +25,13 @@ pub async fn http_handler(

Ok(tag.into())
}

pub async fn direct_handler(
id: String,
post_service: Arc<Box<dyn PostService>>,
) -> Option<TagContainer> {
http_handler((TagRequestContent { id, post_service },))
.await
.ok()
.map(|s| s.container)
}
3 changes: 0 additions & 3 deletions blog-server-api/src/endpoints/tag/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,3 @@ mod response_content_failure;
mod response_content_success;

pub use handler::*;
pub use request_content::*;
pub use response_content_failure::*;
pub use response_content_success::*;
4 changes: 2 additions & 2 deletions blog-server-api/src/endpoints/tag/request_content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use screw_api::request::{ApiRequestContent, ApiRequestOriginContent};
use std::sync::Arc;

pub struct TagRequestContent {
pub id: String,
pub post_service: Arc<Box<dyn PostService>>,
pub(super) id: String,
pub(super) post_service: Arc<Box<dyn PostService>>,
}

impl<Extensions> ApiRequestContent<Extensions> for TagRequestContent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use screw_api::response::{ApiResponseContentBase, ApiResponseContentSuccess};

#[derive(Debug, Clone)]
pub struct TagResponseContentSuccess {
pub container: TagContainer,
pub(super) container: TagContainer,
}

impl Into<TagResponseContentSuccess> for ServiceTag {
Expand Down
Loading