Skip to content

Commit fa98cff

Browse files
committed
Allow serving the sparse index directly from the database
Only used for local development and test environments.
1 parent 2a71fe6 commit fa98cff

File tree

2 files changed

+76
-0
lines changed

2 files changed

+76
-0
lines changed

src/controllers/krate/metadata.rs

+60
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
use std::cmp::Reverse;
88
use std::str::FromStr;
99

10+
use conduit::{Body, Response};
11+
1012
use crate::controllers::frontend_prelude::*;
1113
use crate::controllers::helpers::pagination::PaginationOptions;
1214

@@ -15,6 +17,7 @@ use crate::models::{
1517
TopVersions, User, Version, VersionOwnerAction,
1618
};
1719
use crate::schema::*;
20+
use crate::util::errors::not_found;
1821
use crate::views::{
1922
EncodableCategory, EncodableCrate, EncodableDependency, EncodableKeyword, EncodableVersion,
2023
};
@@ -396,3 +399,60 @@ pub fn reverse_dependencies(req: &mut dyn RequestExt) -> EndpointResult {
396399
"meta": { "total": total },
397400
})))
398401
}
402+
403+
/// Generate the sparse registry config.json file
404+
pub fn config_json(req: &mut dyn RequestExt) -> EndpointResult {
405+
let headers = req.headers();
406+
let proto = headers
407+
.get("X-Forwarded-Proto")
408+
.and_then(|v| v.to_str().ok())
409+
.unwrap_or_else(|| {
410+
if req.app().config.env() == crate::Env::Development {
411+
"http"
412+
} else {
413+
"https"
414+
}
415+
});
416+
let domain_name = headers
417+
.get("X-Forwarded-Host")
418+
.or_else(|| headers.get(http::header::HOST))
419+
.and_then(|v| v.to_str().ok())
420+
.unwrap_or_else(|| &req.app().config.domain_name);
421+
422+
let dl = format!("{proto}://{domain_name}/api/v1/crates");
423+
let api = format!("{proto}://{domain_name}/");
424+
425+
#[derive(Serialize)]
426+
struct R {
427+
dl: String,
428+
api: String,
429+
}
430+
Ok(req.json(&R { dl, api }))
431+
}
432+
433+
/// Generate a sparse registry index file
434+
pub fn versions_registry(req: &mut dyn RequestExt) -> EndpointResult {
435+
let crate_name = &req.params()["crate_id"];
436+
437+
let x1 = req.params()["x1"].as_str();
438+
let x2 = req.params().find("x2");
439+
if (x1, x2)
440+
!= match crate_name.len() {
441+
1 => ("1", None),
442+
2 => ("2", None),
443+
3 => ("3", Some(&crate_name[0..1])),
444+
_ => (&crate_name[0..2], Some(&crate_name[2..4])),
445+
}
446+
{
447+
return Err(not_found());
448+
}
449+
450+
let conn = req.db_read()?;
451+
let krate: Crate = Crate::by_name(crate_name).first(&*conn)?;
452+
let body = krate.index_metadata(&*conn)?;
453+
454+
Ok(Response::builder()
455+
.header(header::CONTENT_TYPE, "text/plain; charset=utf-8")
456+
.body(Body::from_vec(body))
457+
.unwrap()) // Header values are well formed, so should not panic
458+
}

src/router.rs

+16
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,22 @@ pub fn build_router(app: &App) -> RouteBuilder {
167167
router.post("/git/index/*path", R(s));
168168
}
169169

170+
if app.config.env() != Env::Production {
171+
// Serve the sparse index. In production this is served from S3.
172+
router.get(
173+
"/api/private/index/:x1/:x2/:crate_id",
174+
C(krate::metadata::versions_registry),
175+
);
176+
router.get(
177+
"/api/private/index/:x1/:crate_id",
178+
C(krate::metadata::versions_registry),
179+
);
180+
router.get(
181+
"/api/private/index/config.json",
182+
C(krate::metadata::config_json),
183+
);
184+
}
185+
170186
router
171187
}
172188

0 commit comments

Comments
 (0)