Skip to content

Commit

Git over HTTPS answers a workspace alias in place

A request under an alias (g1t.sh/g1t/<repo>.git) is answered as the workspace's repository (flagon-io/<repo>), resolved where renamed and transferred paths are, rather than redirected: pushes and some clients do not follow redirects.

syntaqxcommitted Parent84ec21bBrowse files
3 files+74−30/3 viewed
+2−1
22 // service answers anonymous git requests with `wrangler dev` (repos.jsonc).
33 //
44 // - Identity knows nobody: credentials name no one, and no workspace was
5−// renamed. Public repositories can be cloned without signing in.
5+// renamed or aliased. Public repositories can be cloned without signing in.
66 // - Events takes every event and audit entry and logs them.
77 // - Security has allowed no secrets; billing says every workspace is free.
88
1414 switch (method) {
1515 case "user_for_git_credentials":
1616 case "resolve_slug":
17+ case "resolve_alias":
1718 return json(null);
1819 case "is_free":
1920 case "plan":
+54−1
3232 pub service: GitService,
3333 }
3434
35+impl GitRequest {
36+ /// The same request for the repository of the same name under
37+ /// `namespace`: where a workspace alias leads.
38+ pub fn under(&self, namespace: &str) -> GitRequest {
39+ GitRequest {
40+ path: RepoPath {
41+ namespace: namespace.to_owned(),
42+ name: self.path.name.clone(),
43+ },
44+ endpoint: self.endpoint,
45+ service: self.service,
46+ }
47+ }
48+}
49+
3550 /// Parses `/<namespace>/<name>[.git]/<endpoint>`, or returns `None` if the
3651 /// request is not git's.
3752 pub fn parse(url: &Url) -> Option<GitRequest> {
216231 Ok(current.and_then(|slug| with_namespace(url, &slug)))
217232 }
218233
234+/// The request under the workspace its first segment is an alias of
235+/// (identity's aliases.rs: `g1t` for `flagon-io`), if it is one. Answered
236+/// in place rather than redirected: a push does not follow a redirect.
237+pub async fn aliased(git: &GitRequest, identity: &Fetcher) -> Result<Option<GitRequest>> {
238+ let slug: Option<String> = g1t_kit::call(
239+ identity,
240+ "resolve_alias",
241+ &g1t_contracts::identity::SlugArgs {
242+ slug: git.path.namespace.clone(),
243+ },
244+ )
245+ .await?;
246+ Ok(slug.map(|slug| git.under(&slug)))
247+}
248+
219249 /// `url` with its repository, the first two path segments, replaced by
220250 /// `to`: where a request for a transferred repository's old path goes.
221251 /// Keeps whether the old address ended in `.git`.
10501080
10511081 #[cfg(test)]
10521082 mod tests {
1053− use super::{Acknowledged, Pushed, RepoPath, Url, ZERO_ID, acknowledged, framed, negotiating, pack_bytes, pushed_branches, refusal, server_timing, transferred, with_head, with_namespace};
1083+ use super::{Acknowledged, GitService, Pushed, RepoPath, Url, ZERO_ID, acknowledged, framed, negotiating, pack_bytes, parse, pushed_branches, refusal, server_timing, transferred, with_head, with_namespace};
10541084
10551085 #[test]
10561086 fn server_timing_names_each_step_and_the_total() {
11591189 }
11601190
11611191 #[test]
1192+ fn an_alias_is_answered_as_its_workspaces_repository() {
1193+ for (address, service) in [
1194+ ("https://g1t.sh/g1t/g1t.git/info/refs?service=git-upload-pack", GitService::UploadPack),
1195+ ("https://g1t.sh/g1t/g1t.git/git-receive-pack", GitService::ReceivePack),
1196+ ("https://g1t.sh/g1t/g1t/git-upload-pack", GitService::UploadPack),
1197+ ] {
1198+ let git = parse(&Url::parse(address).unwrap()).unwrap();
1199+ assert_eq!(git.path.namespace, "g1t", "{address}");
1200+ let canonical = git.under("flagon-io");
1201+ assert_eq!(
1202+ canonical.path,
1203+ RepoPath {
1204+ namespace: "flagon-io".into(),
1205+ name: "g1t".into(),
1206+ },
1207+ "{address}"
1208+ );
1209+ assert_eq!(canonical.service, service);
1210+ assert_eq!(canonical.endpoint, git.endpoint);
1211+ }
1212+ }
1213+
1214+ #[test]
11621215 fn a_renamed_workspace_keeps_the_rest_of_the_address() {
11631216 let url = worker::Url::parse(
11641217 "https://g1t.sh/acme/rocket.git/info/refs?service=git-upload-pack",
+18−1
15681568 };
15691569 let (found, viewer) =
15701570 futures_util::future::join(lookup, git_http::viewer(&request, &identity)).await;
1571− let found = found?;
1571+ let mut found = found?;
15721572 timing.mark("repo");
1573+ // A workspace alias staff set (identity's aliases.rs: `g1t` for
1574+ // `flagon-io`) is answered in place, as the repository under the
1575+ // workspace's slug: pushes and some clients do not follow
1576+ // redirects. Everything after this sees only the workspace's slug.
1577+ let aliased = match found {
1578+ Some(_) => None,
1579+ None => git_http::aliased(git, &identity).await?,
1580+ };
1581+ if let Some(aliased) = &aliased {
1582+ found = if write {
1583+ self.registry.by_path(&aliased.path).await?
1584+ } else {
1585+ self.registry.by_path_recent(&aliased.path).await?
1586+ };
1587+ timing.mark("alias");
1588+ }
1589+ let git = aliased.as_ref().unwrap_or(git);
15731590 if found.is_none() {
15741591 // A workspace that was renamed: git follows a redirect when it
15751592 // first asks for refs, and uses the new address from then on.