RSS support
This commit is contained in:
1 parent
c79d5a479a
commit
aa06d2c5ef
14 files changed
+296
-58
No files matched your search
Generated
+139
@@ -46,6 +46,19 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atom_syndication"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "21fb6a0b39c6517edafe46f8137e53c51742425a4dae1c73ee12264a37ad7541"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"derive_builder",
|
||||
"diligent-date-parser",
|
||||
"never",
|
||||
"quick-xml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.14"
|
||||
@@ -148,6 +161,7 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
name = "blog_server"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"atom_syndication",
|
||||
"axum",
|
||||
"chrono",
|
||||
"knuffel",
|
||||
@@ -156,6 +170,7 @@ dependencies = [
|
||||
"miette",
|
||||
"notify",
|
||||
"pulldown-cmark",
|
||||
"rss",
|
||||
"syntect",
|
||||
"tokio",
|
||||
"tower",
|
||||
@@ -223,6 +238,90 @@ dependencies = [
|
||||
"syntect",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f2c43f534ea4b0b049015d00269734195e6d3f0f6635cb692251aca6f9f8b3c"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e91455b86830a1c21799d94524df0845183fa55bafd9aa137b01c7d1065fa36"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.12.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29b5acf0dea37a7f66f7b25d2c5e93fd46f8f6968b1a5d7a3e02e97768afc95a"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d13202debe11181040ae9063d739fa32cfcaaebe2275fe387703460ae2365b30"
|
||||
dependencies = [
|
||||
"derive_builder_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder_core"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66e616858f6187ed828df7c64a6d71720d83767a7f19740b2d1b6fe6327b36e5"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder_macro"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "58a94ace95092c5acb1e97a7e846b310cfbd499652f72297da7493f618a98d73"
|
||||
dependencies = [
|
||||
"derive_builder_core",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diligent-date-parser"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2d0fd95c7c02e2d6c588c6c5628466fff9bdde4b8c6196465e087b08e792720"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "encoding_rs"
|
||||
version = "0.8.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.16"
|
||||
@@ -436,6 +535,12 @@ dependencies = [
|
||||
"want",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.8.1"
|
||||
@@ -742,6 +847,12 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "never"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c96aba5aa877601bb3f6dd6a63a969e1f82e60646e81e71b14496995e9853c91"
|
||||
|
||||
[[package]]
|
||||
name = "notify"
|
||||
version = "4.0.17"
|
||||
@@ -967,6 +1078,16 @@ dependencies = [
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.22.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8533f14c8382aaad0d592c812ac3b826162128b65662331e1127b45c3d18536b"
|
||||
dependencies = [
|
||||
"encoding_rs",
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.18"
|
||||
@@ -1002,6 +1123,18 @@ version = "0.6.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
|
||||
|
||||
[[package]]
|
||||
name = "rss"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acaf1331b7fc4edc3c2920819fee1766c27e8d40da593155832db3d6dea64e92"
|
||||
dependencies = [
|
||||
"atom_syndication",
|
||||
"derive_builder",
|
||||
"never",
|
||||
"quick-xml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.21"
|
||||
@@ -1121,6 +1254,12 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "supports-color"
|
||||
version = "1.3.0"
|
||||
|
||||
@@ -15,6 +15,9 @@ tower = { version = "0.4", features = ["limit"] }
|
||||
tower-http = { version = "0.3", features = ["fs", "trace"] }
|
||||
# Compile-time HTTP templating
|
||||
maud = "0.23"
|
||||
# Serialisation for RSS and Atom
|
||||
atom_syndication = "0.11"
|
||||
rss = "2"
|
||||
# KDL parsing
|
||||
knuffel = "2"
|
||||
# CommonMark parsing
|
||||
|
||||
+26
-10
@@ -16,16 +16,32 @@ use codeblock::CodeBlockRenderer;
|
||||
use posts_store::ConcurrentPostsStore;
|
||||
use render::Renderer;
|
||||
|
||||
#[derive(knuffel::Decode)]
|
||||
struct Config {
|
||||
#[derive(knuffel::Decode, Clone, Debug)]
|
||||
pub struct Config {
|
||||
#[knuffel(child, unwrap(argument))]
|
||||
bind: String,
|
||||
#[knuffel(child, unwrap(argument))]
|
||||
concurrency_limit: usize,
|
||||
#[knuffel(child, unwrap(argument))]
|
||||
posts_dir: PathBuf,
|
||||
#[knuffel(child, unwrap(argument))]
|
||||
static_dir: PathBuf,
|
||||
#[knuffel(child)]
|
||||
rss: RssConfig,
|
||||
}
|
||||
|
||||
#[derive(knuffel::Decode, Clone, Debug)]
|
||||
pub struct RssConfig {
|
||||
#[knuffel(child, unwrap(argument))]
|
||||
concurrency_limit: usize,
|
||||
num_posts: usize,
|
||||
#[knuffel(child, unwrap(argument))]
|
||||
title: String,
|
||||
#[knuffel(child, unwrap(argument))]
|
||||
ttl: u32,
|
||||
#[knuffel(child, unwrap(argument))]
|
||||
protocol: String,
|
||||
#[knuffel(child, unwrap(argument))]
|
||||
domain: String,
|
||||
}
|
||||
|
||||
fn main() -> miette::Result<()> {
|
||||
@@ -79,18 +95,18 @@ fn main() -> miette::Result<()> {
|
||||
.block_on(run(config, posts_store))
|
||||
}
|
||||
|
||||
async fn run(config: Config, posts_store: ConcurrentPostsStore) -> miette::Result<()> {
|
||||
let service = service::site_service(
|
||||
posts_store,
|
||||
&config.static_dir,
|
||||
config.concurrency_limit
|
||||
);
|
||||
|
||||
async fn run(
|
||||
config: Config,
|
||||
posts_store: ConcurrentPostsStore,
|
||||
) -> miette::Result<()>
|
||||
{
|
||||
let bind_address = &config.bind
|
||||
.parse()
|
||||
.into_diagnostic()
|
||||
.wrap_err_with(|| format!("Failed to parse socket address \"{}\"", config.bind))?;
|
||||
|
||||
let service = service::site_service(config, posts_store);
|
||||
|
||||
info!(address = %bind_address, "Starting server");
|
||||
|
||||
Server::try_bind(bind_address)
|
||||
|
||||
@@ -125,12 +125,12 @@ impl Post {
|
||||
) -> Result<Self, ParseError>
|
||||
{
|
||||
let mdpost = MdPost::parse(file_name, source)?;
|
||||
Ok(Self::from_mdpost(post_id, code_renderer, created, updated, mdpost))
|
||||
Ok(Self::from_mdpost(code_renderer, post_id, created, updated, mdpost))
|
||||
}
|
||||
|
||||
fn from_mdpost(
|
||||
id: PostId,
|
||||
code_renderer: &CodeBlockRenderer,
|
||||
id: PostId,
|
||||
created: DateTime<Utc>,
|
||||
updated: DateTime<Utc>,
|
||||
mdpost: MdPost,
|
||||
|
||||
@@ -10,9 +10,11 @@ use chrono::{DateTime, Utc};
|
||||
use notify::DebouncedEvent;
|
||||
use tracing::{info, warn, error};
|
||||
|
||||
use crate::codeblock::CodeBlockRenderer;
|
||||
use crate::post::{ParseError, Post, PostId};
|
||||
use crate::posts_store::ConcurrentPostsStore;
|
||||
use crate::{
|
||||
codeblock::CodeBlockRenderer,
|
||||
post::{ParseError, Post, PostId},
|
||||
posts_store::ConcurrentPostsStore,
|
||||
};
|
||||
|
||||
pub struct Renderer {
|
||||
posts: ConcurrentPostsStore,
|
||||
@@ -125,7 +127,8 @@ impl Renderer {
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
fn remove(&self, target: &EventTarget) {
|
||||
self.posts.write_blocking().remove(&target.id);
|
||||
let mut guard = self.posts.write_blocking();
|
||||
guard.remove(&target.id);
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use maud::html;
|
||||
|
||||
use crate::template;
|
||||
use super::response::HtmlResponse;
|
||||
use super::response::Html;
|
||||
|
||||
pub async fn handle() -> HtmlResponse {
|
||||
HtmlResponse::new()
|
||||
pub async fn handle() -> Html {
|
||||
Html::new()
|
||||
.with_title_static("Contact")
|
||||
.with_crawler_permissive()
|
||||
.with_head(html! {
|
||||
|
||||
@@ -5,10 +5,10 @@ use crate::{
|
||||
posts_store::ConcurrentPostsStore,
|
||||
template,
|
||||
};
|
||||
use super::response::HtmlResponse;
|
||||
use super::response::Html;
|
||||
|
||||
pub async fn handle(Extension(posts): Extension<ConcurrentPostsStore>) -> HtmlResponse {
|
||||
HtmlResponse::new()
|
||||
pub async fn handle(Extension(posts): Extension<ConcurrentPostsStore>) -> Html {
|
||||
Html::new()
|
||||
.with_title_static("Pantonshire")
|
||||
.with_crawler_permissive()
|
||||
.with_head(html! {
|
||||
|
||||
@@ -3,6 +3,7 @@ mod index;
|
||||
mod post;
|
||||
mod posts_list;
|
||||
mod response;
|
||||
mod rss;
|
||||
mod site;
|
||||
mod static_content;
|
||||
|
||||
|
||||
@@ -2,18 +2,18 @@ use axum::extract::{Extension, Path};
|
||||
use maud::html;
|
||||
|
||||
use crate::posts_store::ConcurrentPostsStore;
|
||||
use super::response::{ErrorResponse, HtmlResponse};
|
||||
use super::response::{Error, Html};
|
||||
|
||||
pub async fn handle(
|
||||
Path(post_id): Path<String>,
|
||||
Extension(posts): Extension<ConcurrentPostsStore>
|
||||
) -> Result<HtmlResponse, ErrorResponse>
|
||||
) -> Result<Html, Error>
|
||||
{
|
||||
let post = posts.get(&post_id)
|
||||
.await
|
||||
.ok_or(ErrorResponse::PostNotFound)?;
|
||||
.ok_or(Error::PostNotFound)?;
|
||||
|
||||
Ok(HtmlResponse::new()
|
||||
Ok(Html::new()
|
||||
.with_crawler_permissive()
|
||||
.with_title_owned(post.title().to_owned())
|
||||
.with_head(html! {
|
||||
|
||||
@@ -5,10 +5,10 @@ use crate::{
|
||||
posts_store::ConcurrentPostsStore,
|
||||
template,
|
||||
};
|
||||
use super::response::HtmlResponse;
|
||||
use super::response::Html;
|
||||
|
||||
pub async fn handle(Extension(posts): Extension<ConcurrentPostsStore>) -> HtmlResponse {
|
||||
HtmlResponse::new()
|
||||
pub async fn handle(Extension(posts): Extension<ConcurrentPostsStore>) -> Html {
|
||||
Html::new()
|
||||
.with_title_static("Articles")
|
||||
.with_crawler_permissive()
|
||||
.with_head(html! {
|
||||
|
||||
@@ -4,31 +4,32 @@ use std::{
|
||||
};
|
||||
|
||||
use axum::{
|
||||
http::StatusCode,
|
||||
response::{IntoResponse, Html, Response},
|
||||
body::{Bytes, Full},
|
||||
http::{header::{self, HeaderValue}, StatusCode},
|
||||
response::{IntoResponse, Response},
|
||||
};
|
||||
use maud::{html, Markup, Render, Escaper, DOCTYPE};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ErrorResponse {
|
||||
pub enum Error {
|
||||
Internal,
|
||||
PostNotFound,
|
||||
StaticResourceNotFound,
|
||||
RouteNotFound,
|
||||
}
|
||||
|
||||
impl ErrorResponse {
|
||||
impl Error {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match self {
|
||||
ErrorResponse::Internal => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
ErrorResponse::PostNotFound => StatusCode::NOT_FOUND,
|
||||
ErrorResponse::StaticResourceNotFound => StatusCode::NOT_FOUND,
|
||||
ErrorResponse::RouteNotFound => StatusCode::NOT_FOUND,
|
||||
Error::Internal => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Error::PostNotFound => StatusCode::NOT_FOUND,
|
||||
Error::StaticResourceNotFound => StatusCode::NOT_FOUND,
|
||||
Error::RouteNotFound => StatusCode::NOT_FOUND,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoResponse for ErrorResponse {
|
||||
impl IntoResponse for Error {
|
||||
fn into_response(self) -> Response {
|
||||
let status_code = self.status_code();
|
||||
|
||||
@@ -51,7 +52,7 @@ impl IntoResponse for ErrorResponse {
|
||||
buf
|
||||
};
|
||||
|
||||
HtmlResponse::new()
|
||||
Html::new()
|
||||
.with_status(status_code)
|
||||
.with_body(html! {
|
||||
p { (status_text) }
|
||||
@@ -61,7 +62,7 @@ impl IntoResponse for ErrorResponse {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct HtmlResponse {
|
||||
pub struct Html {
|
||||
status: StatusCode,
|
||||
title: Cow<'static, str>,
|
||||
head: Option<Markup>,
|
||||
@@ -69,7 +70,7 @@ pub struct HtmlResponse {
|
||||
crawler_hints: CrawlerHints,
|
||||
}
|
||||
|
||||
impl HtmlResponse {
|
||||
impl Html {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
status: StatusCode::OK,
|
||||
@@ -117,13 +118,13 @@ impl HtmlResponse {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for HtmlResponse {
|
||||
impl Default for Html {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoResponse for HtmlResponse {
|
||||
impl IntoResponse for Html {
|
||||
fn into_response(self) -> Response {
|
||||
let html_doc = html! {
|
||||
(DOCTYPE)
|
||||
@@ -145,7 +146,7 @@ impl IntoResponse for HtmlResponse {
|
||||
}
|
||||
};
|
||||
|
||||
(self.status, Html(html_doc.into_string()))
|
||||
(self.status, axum::response::Html(html_doc.into_string()))
|
||||
.into_response()
|
||||
}
|
||||
}
|
||||
@@ -261,3 +262,29 @@ impl Render for CrawlerHints {
|
||||
let _result = self.write_meta_list_to(escaper);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Rss<T>(pub T);
|
||||
|
||||
impl<T: Into<Full<Bytes>>> IntoResponse for Rss<T> {
|
||||
fn into_response(self) -> Response {
|
||||
let headers = [
|
||||
(header::CONTENT_TYPE, HeaderValue::from_static("application/rss+xml")),
|
||||
];
|
||||
|
||||
(headers, self.0.into())
|
||||
.into_response()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Atom<T>(pub T);
|
||||
|
||||
impl<T: Into<Full<Bytes>>> IntoResponse for Atom<T> {
|
||||
fn into_response(self) -> Response {
|
||||
let headers = [
|
||||
(header::CONTENT_TYPE, HeaderValue::from_static("application/atom+xml")),
|
||||
];
|
||||
|
||||
(headers, self.0.into())
|
||||
.into_response()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use axum::{
|
||||
body::Bytes,
|
||||
extract::Extension,
|
||||
};
|
||||
|
||||
use super::response::Rss;
|
||||
use crate::{posts_store::ConcurrentPostsStore, Config};
|
||||
|
||||
pub async fn handle(
|
||||
Extension(config): Extension<Arc<Config>>,
|
||||
Extension(posts): Extension<ConcurrentPostsStore>,
|
||||
) -> Rss<Bytes> {
|
||||
let rss_items = posts.read()
|
||||
.await
|
||||
.iter_by_created()
|
||||
.take(config.rss.num_posts)
|
||||
.map(|post| {
|
||||
rss::ItemBuilder::default()
|
||||
.title(Some(post.title().to_owned()))
|
||||
.link(Some(format!(
|
||||
"{}://{}/articles/{}",
|
||||
config.rss.protocol,
|
||||
config.rss.domain,
|
||||
post.id()
|
||||
)))
|
||||
.pub_date(Some(post.created().to_rfc2822()))
|
||||
.build()
|
||||
})
|
||||
.collect::<Vec<rss::Item>>();
|
||||
|
||||
Rss(rss::ChannelBuilder::default()
|
||||
.title(config.rss.title.clone())
|
||||
.link(format!(
|
||||
"{}://{}",
|
||||
config.rss.protocol, config.rss.domain
|
||||
))
|
||||
.ttl(Some(config.rss.ttl.to_string()))
|
||||
.items(rss_items)
|
||||
.build()
|
||||
.to_string()
|
||||
.into())
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
use axum::{
|
||||
handler::Handler,
|
||||
@@ -11,35 +11,40 @@ use tower::limit::ConcurrencyLimitLayer;
|
||||
use tower_http::trace::TraceLayer;
|
||||
use tracing::info;
|
||||
|
||||
use crate::posts_store::ConcurrentPostsStore;
|
||||
use crate::{
|
||||
Config,
|
||||
posts_store::ConcurrentPostsStore
|
||||
};
|
||||
use super::{
|
||||
contact,
|
||||
index,
|
||||
post,
|
||||
posts_list,
|
||||
response::ErrorResponse,
|
||||
response::Error,
|
||||
rss,
|
||||
static_content,
|
||||
};
|
||||
|
||||
pub fn service(
|
||||
config: Config,
|
||||
posts_store: ConcurrentPostsStore,
|
||||
static_dir: &Path,
|
||||
concurrency_limit: usize
|
||||
) -> Router
|
||||
{
|
||||
Router::new()
|
||||
.route("/", get(index::handle))
|
||||
.route("/rss.xml", get(rss::handle))
|
||||
.route("/contact", get(contact::handle))
|
||||
.route("/articles", get(posts_list::handle))
|
||||
.route("/articles/:post_id", get(post::handle))
|
||||
.nest("/static", static_content::service(static_dir))
|
||||
.nest("/static", static_content::service(&config.static_dir))
|
||||
.fallback(handle_fallback.into_service())
|
||||
.layer(ConcurrencyLimitLayer::new(concurrency_limit))
|
||||
.layer(ConcurrencyLimitLayer::new(config.concurrency_limit))
|
||||
.layer(TraceLayer::new_for_http())
|
||||
.layer(Extension(Arc::new(config)))
|
||||
.layer(Extension(posts_store))
|
||||
}
|
||||
|
||||
pub async fn handle_fallback(uri: Uri) -> ErrorResponse {
|
||||
pub async fn handle_fallback(uri: Uri) -> Error {
|
||||
info!(path = %uri.path(), "Requested resource not found");
|
||||
ErrorResponse::RouteNotFound
|
||||
Error::RouteNotFound
|
||||
}
|
||||
@@ -15,7 +15,7 @@ use tower::ServiceExt;
|
||||
use tower_http::services::ServeDir;
|
||||
use tracing::{info, error};
|
||||
|
||||
use super::response::ErrorResponse;
|
||||
use super::response::Error;
|
||||
|
||||
pub fn service(static_dir: &Path) -> MethodRouter<Body, Infallible> {
|
||||
let fallback_service = handle_fallback
|
||||
@@ -29,12 +29,12 @@ pub fn service(static_dir: &Path) -> MethodRouter<Body, Infallible> {
|
||||
.handle_error(handle_error)
|
||||
}
|
||||
|
||||
pub async fn handle_fallback(uri: Uri) -> ErrorResponse {
|
||||
pub async fn handle_fallback(uri: Uri) -> Error {
|
||||
info!(path = %uri.path(), "Requested static file not found");
|
||||
ErrorResponse::StaticResourceNotFound
|
||||
Error::StaticResourceNotFound
|
||||
}
|
||||
|
||||
pub async fn handle_error(uri: Uri, err: io::Error) -> ErrorResponse {
|
||||
pub async fn handle_error(uri: Uri, err: io::Error) -> Error {
|
||||
error!(path = %uri.path(), err = %err, "IO error");
|
||||
ErrorResponse::Internal
|
||||
Error::Internal
|
||||
}
|
||||
Reference in new issue
Block a user