Skip to content

Commit 5dfe87a

Browse files
committed
feat(serve): support contributors.txt
1 parent 2a7c039 commit 5dfe87a

File tree

4 files changed

+78
-36
lines changed

4 files changed

+78
-36
lines changed

Cargo.toml

+24-24
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ version = "0.0.20"
44
edition = "2021"
55
license = "MPL-2.0"
66
authors = [
7-
"Florian Dieminger <me@fiji-flo.de>",
8-
"The MDN Engineering Team <mdn-dev@mozilla.com>",
7+
"Florian Dieminger <me@fiji-flo.de>",
8+
"The MDN Engineering Team <mdn-dev@mozilla.com>",
99
]
1010
homepage = "https://github.com/mdn/rari"
1111
repository = "https://github.com/mdn/rari"
@@ -30,27 +30,27 @@ codegen-units = 1
3030
[workspace]
3131
resolver = "2"
3232
members = [
33-
"crates/rari-data",
34-
"crates/rari-utils",
35-
"crates/rari-deps",
36-
"crates/rari-types",
37-
"crates/rari-templ-func",
38-
"crates/rari-md",
39-
"crates/rari-doc",
40-
"crates/rari-linter",
41-
"crates/rari-tools",
42-
"crates/css-syntax",
43-
"crates/css-syntax-types",
44-
"crates/css-definition-syntax",
45-
"crates/diff-test",
33+
"crates/rari-data",
34+
"crates/rari-utils",
35+
"crates/rari-deps",
36+
"crates/rari-types",
37+
"crates/rari-templ-func",
38+
"crates/rari-md",
39+
"crates/rari-doc",
40+
"crates/rari-linter",
41+
"crates/rari-tools",
42+
"crates/css-syntax",
43+
"crates/css-syntax-types",
44+
"crates/css-definition-syntax",
45+
"crates/diff-test",
4646
]
4747

4848
[workspace.package]
4949
edition = "2021"
5050
license = "MPL-2.0"
5151
authors = [
52-
"Florian Dieminger <me@fiji-flo.de>",
53-
"The MDN Engineering Team <mdn-dev@mozilla.com>",
52+
"Florian Dieminger <me@fiji-flo.de>",
53+
"The MDN Engineering Team <mdn-dev@mozilla.com>",
5454
]
5555
rust-version = "1.81"
5656

@@ -81,10 +81,10 @@ html-escape = "0.2"
8181
ignore = "0.4"
8282
rayon = "1"
8383
reqwest = { version = "0.12", default-features = false, features = [
84-
"blocking",
85-
"json",
86-
"rustls-tls",
87-
"gzip",
84+
"blocking",
85+
"json",
86+
"rustls-tls",
87+
"gzip",
8888
] }
8989
indoc = "2"
9090
base64 = "0.22"
@@ -108,9 +108,9 @@ anyhow.workspace = true
108108
dashmap.workspace = true
109109

110110
self_update = { version = "0.41", default-features = false, features = [
111-
"rustls",
112-
"compression-flate2",
113-
"compression-zip-deflate",
111+
"rustls",
112+
"compression-flate2",
113+
"compression-zip-deflate",
114114
] }
115115
clap = { version = "4.5.1", features = ["derive"] }
116116
clap-verbosity-flag = "2"

crates/rari-cli/serve.rs

+49-4
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ use std::str::FromStr;
33
use std::sync::atomic::AtomicU64;
44
use std::sync::Arc;
55

6+
use axum::body::Body;
67
use axum::extract::{Path, Request, State};
7-
use axum::http::StatusCode;
8+
use axum::http::{header, StatusCode};
89
use axum::response::{IntoResponse, Response};
910
use axum::routing::get;
1011
use axum::{Json, Router};
12+
use rari_doc::cached_readers::wiki_histories;
13+
use rari_doc::contributors::contributors_txt;
1114
use rari_doc::error::DocError;
1215
use rari_doc::issues::{to_display_issues, InMemoryLayer};
1316
use rari_doc::pages::json::BuiltPage;
@@ -28,14 +31,23 @@ struct SearchItem {
2831
title: String,
2932
url: String,
3033
}
34+
35+
async fn handler(state: State<Arc<InMemoryLayer>>, req: Request) -> Response<Body> {
36+
if req.uri().path().ends_with("/contributors.txt") {
37+
get_contributors_handler(req).await.into_response()
38+
} else {
39+
get_json_handler(state, req).await.into_response()
40+
}
41+
}
42+
3143
async fn get_json_handler(
3244
State(memory_layer): State<Arc<InMemoryLayer>>,
3345
req: Request,
3446
) -> Result<Json<BuiltPage>, AppError> {
47+
let url = req.uri().path();
3548
let req_id = REQ_COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
3649
let span = span!(Level::WARN, "serve", req = req_id);
3750
let _enter1 = span.enter();
38-
let url = req.uri().path();
3951
let mut json = get_json(url)?;
4052
if let BuiltPage::Doc(json_doc) = &mut json {
4153
let m = memory_layer.get_events();
@@ -66,6 +78,38 @@ fn get_json(url: &str) -> Result<BuiltPage, DocError> {
6678
Ok(json)
6779
}
6880

81+
async fn get_contributors_handler(req: Request) -> impl IntoResponse {
82+
let url = req.uri().path();
83+
match get_contributors(url.strip_suffix("/contributors.txt").unwrap_or(url)) {
84+
Ok(contributors_txt_str) => (
85+
StatusCode::OK,
86+
[(header::CONTENT_TYPE, "text/plain")],
87+
contributors_txt_str,
88+
)
89+
.into_response(),
90+
Err(e) => {
91+
tracing::error!("error generating contributors.txt for {url}: {e:?}");
92+
(StatusCode::INTERNAL_SERVER_ERROR).into_response()
93+
}
94+
}
95+
}
96+
97+
fn get_contributors(url: &str) -> Result<String, AppError> {
98+
let page = Page::from_url_with_fallback(url)?;
99+
let json = page.build()?;
100+
let github_file_url = if let BuiltPage::Doc(ref doc) = json {
101+
&doc.doc.source.github_url
102+
} else {
103+
""
104+
};
105+
let wiki_histories = wiki_histories();
106+
let wiki_history = wiki_histories
107+
.get(&page.locale())
108+
.and_then(|wh| wh.get(page.slug()));
109+
let contributors_txt_str = contributors_txt(wiki_history, github_file_url);
110+
Ok(contributors_txt_str)
111+
}
112+
69113
async fn get_search_index_handler(
70114
Path(locale): Path<String>,
71115
) -> Result<Json<Vec<SearchItem>>, AppError> {
@@ -118,10 +162,11 @@ fn get_search_index(locale: Locale) -> Result<Vec<SearchItem>, DocError> {
118162
Ok(out)
119163
}
120164

165+
#[derive(Debug)]
121166
struct AppError(anyhow::Error);
122167

123168
impl IntoResponse for AppError {
124-
fn into_response(self) -> Response {
169+
fn into_response(self) -> Response<Body> {
125170
(StatusCode::INTERNAL_SERVER_ERROR, error!("🤷: {}", self.0)).into_response()
126171
}
127172
}
@@ -142,7 +187,7 @@ pub fn serve(memory_layer: InMemoryLayer) -> Result<(), anyhow::Error> {
142187
.block_on(async {
143188
let app = Router::new()
144189
.route("/:locale/search-index.json", get(get_search_index_handler))
145-
.fallback(get_json_handler)
190+
.fallback(handler)
146191
.with_state(Arc::new(memory_layer));
147192

148193
let listener = tokio::net::TcpListener::bind("0.0.0.0:8083").await.unwrap();

crates/rari-doc/src/cached_readers.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ pub fn contributor_spotlight_files() -> Cow<'static, UrlToPageMap> {
613613
///
614614
/// - Panics if the translated content root or individual directory names are invalid.
615615
/// - Panics if the `_wikihistory.json` file is missing or contains malformed JSON.
616-
pub(crate) fn wiki_histories() -> Cow<'static, WikiHistories> {
616+
pub fn wiki_histories() -> Cow<'static, WikiHistories> {
617617
fn gather() -> Result<WikiHistories, DocError> {
618618
let mut map = HashMap::new();
619619
if let Some(ctr) = content_translated_root() {

crates/rari-doc/src/contributors.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ use rari_types::locale::Locale;
44
use serde::Deserialize;
55

66
#[derive(Clone, Debug, Deserialize)]
7-
pub(crate) struct WikiHistoryEntry {
7+
pub struct WikiHistoryEntry {
88
pub contributors: Vec<String>,
99
}
1010

11-
pub(crate) type WikiHistory = HashMap<String, WikiHistoryEntry>;
12-
pub(crate) type WikiHistories = HashMap<Locale, WikiHistory>;
11+
pub type WikiHistory = HashMap<String, WikiHistoryEntry>;
12+
pub type WikiHistories = HashMap<Locale, WikiHistory>;
1313

1414
/// Generates a contributors text report summarizing commit history and original Wiki contributors.
1515
///
@@ -61,10 +61,7 @@ pub(crate) type WikiHistories = HashMap<Locale, WikiHistory>;
6161
/// // # Contributors by commit history
6262
/// // https://github.com/user/repo/commits/main/file.txt
6363
/// ```
64-
pub(crate) fn contributors_txt(
65-
wiki_history: Option<&WikiHistoryEntry>,
66-
github_file_url: &str,
67-
) -> String {
64+
pub fn contributors_txt(wiki_history: Option<&WikiHistoryEntry>, github_file_url: &str) -> String {
6865
let mut out = String::new();
6966
out.extend([
7067
"# Contributors by commit history\n",

0 commit comments

Comments
 (0)