Skip to content

Commit 828b844

Browse files
committed
Redirect to ".md" page if client expects Markdown format
1 parent 3251719 commit 828b844

4 files changed

Lines changed: 79 additions & 11 deletions

File tree

Cargo.lock

Lines changed: 52 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ strip = "debuginfo"
1414
ammonia = "4.1.3"
1515
atom_syndication = { version = "0.12.9", features = ["serde"] }
1616
axum = { version = "0.8.9", features = ["macros"] }
17-
axum-extra = { version = "0.12.6", features = ["with-rejection"] }
17+
axum-extra = { version = "0.12.6", features = ["with-rejection", "typed-header"] }
1818
axum-login = "0.18.0"
1919
chrono = { version = "0.4.45", features = [
2020
"serde",
@@ -39,9 +39,11 @@ gel-derive = { git = "https://github.com/geldata/gel-rust" }
3939
gel-errors = { git = "https://github.com/geldata/gel-rust", features = ["miette"] }
4040
gel-protocol = { git = "https://github.com/geldata/gel-rust", features = ["all-types"] }
4141
gel-tokio = { git = "https://github.com/geldata/gel-rust", features = ["miette-errors"] }
42+
headers-accept = "0.3.0"
4243
http = "1.4.2"
4344
indexmap = { version = "2.14.0", features = ["serde"] }
4445
libpassgen = "1.0.3"
46+
mediatype = "0.21.0"
4547
miette = { version = "7.6.0", features = ["fancy", "serde"] }
4648
mime_guess = "2.0.5"
4749
minijinja = { version = "2.21.0", features = ["loader", "internal_debug"] }

src/front/structs.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ impl LaxPaging {
1717
/// The type is NonZeroU16 because our website is small enough for page number
1818
/// to be fit in u16.
1919
pub fn get_page_as_number(&self) -> NonZeroU16 {
20-
self.page.as_deref().and_then(|s| s.parse().ok()).unwrap_or(NonZeroU16::MIN)
20+
self.page
21+
.as_deref()
22+
.and_then(|s| s.parse().ok())
23+
.unwrap_or(NonZeroU16::MIN)
2124
}
2225
}
2326

src/front/views/blog.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,12 @@ use std::num::NonZeroU16;
33
use axum::extract::{OriginalUri, Path, Query, State};
44
use axum::http::StatusCode;
55
use axum::response::{Html, Result as AxumResult};
6+
use axum_extra::TypedHeader;
7+
use headers_accept::Accept;
68
use http::header::LOCATION;
79
use indexmap::indexmap;
10+
use mediatype::media_type;
11+
use mediatype::names::MARKDOWN;
812
use minijinja::{context, value::Value as MJValue};
913
use str_macro::str;
1014
use tower_sessions::Session;
@@ -19,10 +23,14 @@ use crate::stores::blog::{get_detailed_post_by_slug, get_next_post, get_previous
1923
use crate::types::{AppState, HtmlOrMd, Paginator};
2024
use crate::utils::html::render_with;
2125

26+
// If the client requests with `Accept: text/markdown` (indicating that it is an AI agent), we will redirect to the ".md" page,
27+
// which returns content in Markdown format. Otherwise, we serve HTML.
2228
pub async fn show_post(
2329
auth_session: AuthSession,
24-
Path((_y, _m, slug_ext)): Path<(u16, u16, String)>,
30+
Path((y, m, slug_ext)): Path<(u16, u16, String)>,
2531
Query(params): Query<PostPageParams>,
32+
// Value of `Accept` header
33+
TypedHeader(accept): TypedHeader<Accept>,
2634
session: Session,
2735
State(state): State<AppState>,
2836
) -> AxumResult<HtmlOrMd> {
@@ -31,6 +39,17 @@ pub async fn show_post(
3139
Some((slug, ".md")) => (slug, true),
3240
_ => (slug_ext.as_str(), false),
3341
};
42+
if !is_md {
43+
let available = vec![media_type!(TEXT / HTML), media_type!(TEXT / MARKDOWN)];
44+
let preferred_type = accept.negotiate(&available);
45+
if preferred_type.map(|t| t.subty) == Some(MARKDOWN) {
46+
return Err((
47+
StatusCode::TEMPORARY_REDIRECT,
48+
format!("/post/{y}/{m}/{slug}.md"),
49+
)
50+
.into());
51+
};
52+
};
3453
let post = get_detailed_post_by_slug(slug, &db)
3554
.await
3655
.map_err(PageError::GelQueryError)?

0 commit comments

Comments
 (0)