Skip to content

Commit 64d262c

Browse files
authored
Merge pull request #365 from Turbo87/downloads-without-placeholders
crates.io: Add support for download URLs without placeholders
2 parents bd836ba + 2c6252e commit 64d262c

File tree

4 files changed

+76
-0
lines changed

4 files changed

+76
-0
lines changed

terragrunt/modules/crates-io/cloudfront-functions/static-router.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,15 @@ function handler(event) {
77
request.uri = request.uri.replace("+", "%2B");
88
}
99

10+
// cargo versions before 1.24 don't support placeholders in the `dl` field
11+
// of the index, so we need to rewrite the download URL to point to the
12+
// crate file instead.
13+
var match = request.uri.match(/^\/crates\/([^\/]+)\/([^\/]+)\/download$/);
14+
if (match) {
15+
var crate = match[1];
16+
var version = match[2];
17+
request.uri = `/crates/${crate}/${crate}-${version}.crate`;
18+
}
19+
1020
return request;
1121
}

terragrunt/modules/crates-io/compute-static/Cargo.lock

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

terragrunt/modules/crates-io/compute-static/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ derive_builder = "0.12.0"
1919
fastly = "0.9.1"
2020
log = "0.4.17"
2121
log-fastly = "0.9.1"
22+
once_cell = "1.18.0"
23+
regex = "1.7.1"
2224
serde = { version = "1.0.152", features = ["derive"] }
2325
serde_json = "1.0.92"
2426
time = { version = "0.3.17", features = ["serde-human-readable"] }

terragrunt/modules/crates-io/compute-static/src/main.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ use fastly::http::{Method, StatusCode};
22
use fastly::{Error, Request, Response};
33
use log::{info, warn, LevelFilter};
44
use log_fastly::Logger;
5+
use once_cell::sync::Lazy;
6+
use regex::Regex;
57
use serde_json::json;
68
use time::OffsetDateTime;
79

@@ -74,6 +76,7 @@ fn handle_request(config: &Config, mut request: Request) -> Result<Response, Err
7476

7577
set_ttl(config, &mut request);
7678
rewrite_urls_with_plus_character(&mut request);
79+
rewrite_download_urls(&mut request);
7780

7881
// Database dump is too big to cache on Fastly
7982
if request.get_url_str().ends_with("db-dump.tar.gz") {
@@ -127,6 +130,28 @@ fn rewrite_urls_with_plus_character(request: &mut Request) {
127130
}
128131
}
129132

133+
/// Rewrite `/crates/{crate}/{version}/download` URLs to
134+
/// `/crates/{crate}/{crate}-{version}.crate`
135+
///
136+
/// cargo versions before 1.24 don't support placeholders in the `dl` field
137+
/// of the index, so we need to rewrite the download URL to point to the
138+
/// crate file instead.
139+
fn rewrite_download_urls(request: &mut Request) {
140+
static RE: Lazy<Regex> = Lazy::new(|| {
141+
Regex::new(r"^/crates/(?P<crate>[^/]+)/(?P<version>[^/]+)/download$").unwrap()
142+
});
143+
144+
let url = request.get_url_mut();
145+
let path = url.path();
146+
147+
if let Some(captures) = RE.captures(path) {
148+
let krate = captures.name("crate").unwrap().as_str();
149+
let version = captures.name("version").unwrap().as_str();
150+
let new_path = format!("/crates/{krate}/{krate}-{version}.crate");
151+
url.set_path(&new_path);
152+
}
153+
}
154+
130155
/// Redirect request to CloudFront
131156
///
132157
/// As of early 2023, certain files are too large to be served through Fastly. One of those is the
@@ -199,3 +224,34 @@ fn build_and_send_log(log_line: LogLineV1Builder, config: &Config) {
199224
}
200225
};
201226
}
227+
228+
#[cfg(test)]
229+
mod tests {
230+
use super::*;
231+
232+
#[test]
233+
fn test_rewrite_download_urls() {
234+
fn test(url: &str, expected: &str) {
235+
let mut request = Request::get(url);
236+
rewrite_download_urls(&mut request);
237+
assert_eq!(request.get_url_str(), expected);
238+
}
239+
240+
test(
241+
"https://static.crates.io/unrelated",
242+
"https://static.crates.io/unrelated",
243+
);
244+
test(
245+
"https://static.crates.io/crates/serde/serde-1.0.0.crate",
246+
"https://static.crates.io/crates/serde/serde-1.0.0.crate",
247+
);
248+
test(
249+
"https://static.crates.io/crates/serde/1.0.0/download",
250+
"https://static.crates.io/crates/serde/serde-1.0.0.crate",
251+
);
252+
test(
253+
"https://static.crates.io/crates/serde/1.0.0-alpha.1+foo-bar/download",
254+
"https://static.crates.io/crates/serde/serde-1.0.0-alpha.1+foo-bar.crate",
255+
);
256+
}
257+
}

0 commit comments

Comments
 (0)