-
Notifications
You must be signed in to change notification settings - Fork 173
fix(proxy): #1588 accept smart-HTTP paths without .git suffix #1642
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -91,6 +91,13 @@ describe('isPackPost()', () => { | |
| expect(isPackPost({ method: 'POST', url: '/a.git/git-upload-pack' } as Request)).toBe(true); | ||
| }); | ||
|
|
||
| it('returns true for git-upload-pack POST without a .git repo suffix', () => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add the negative that fixes the new boundary? isPackPost({ method: 'POST', url: '/git-upload-pack' }) must stay false, a single segment isn't a repo. It holds today, but nothing here would catch a future simplification of this regex that opens it up. |
||
| expect(isPackPost({ method: 'POST', url: '/a/b/git-upload-pack' } as Request)).toBe(true); | ||
| expect( | ||
| isPackPost({ method: 'POST', url: '/github.com/org/repo/git-receive-pack' } as Request), | ||
| ).toBe(true); | ||
| }); | ||
|
|
||
| it('returns false for other URLs', () => { | ||
| expect(isPackPost({ method: 'POST', url: '/info/refs' } as Request)).toBe(false); | ||
| }); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -75,6 +75,25 @@ describe('url helpers and filter functions used in the proxy', () => { | |
| expect(processUrlPath(VERY_LONG_PATH)).toBeNull(); | ||
| }); | ||
|
|
||
| it('processUrlPath should parse smart-HTTP paths without a .git repo suffix', () => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you add the cases that pin the ordering down? Every input here has a repo name with no .git in it, which is why the problem isn't visible:
The last one guards the Action constructor path, which relies on processUrlPath returning null rather than inventing a repo when there's nothing to split on. |
||
| expect(processUrlPath('/octocat/hello-world/info/refs?service=git-upload-pack')).toEqual({ | ||
| repoPath: '/octocat/hello-world.git', | ||
| gitPath: '/info/refs?service=git-upload-pack', | ||
| }); | ||
|
|
||
| expect( | ||
| processUrlPath('/github.com/octocat/hello-world/info/refs?service=git-upload-pack'), | ||
| ).toEqual({ | ||
| repoPath: '/github.com/octocat/hello-world.git', | ||
| gitPath: '/info/refs?service=git-upload-pack', | ||
| }); | ||
|
|
||
| expect(processUrlPath('/org/owner/repo/git-upload-pack')).toEqual({ | ||
| repoPath: '/org/owner/repo.git', | ||
| gitPath: '/git-upload-pack', | ||
| }); | ||
| }); | ||
|
|
||
| it('processGitUrl should return breakdown of a git URL separating out the protocol, host and repository path', () => { | ||
| expect(processGitUrl('https://somegithost.com/octocat/hello-world.git')).toEqual({ | ||
| protocol: 'https://', | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fallback is only reached when PROXIED_URL_PATH_REGEX fails, but that regex is unanchored, and String.match doesn't have to consume the whole string, so it matches almost any path containing .git and silently drops the rest. That includes paths where .git sits inside the repo name:
/github.com/finos/.github/info/refs?service=git-upload-pack
consumed: /github.com/finos/.git
dropped: hub/info/refs?service=git-upload-pack
→ repoPath "/github.com/finos/.git", gitPath "/"
validGitRequest("/") then rejects it, so the new fallback is dead code for these paths and the user still gets Invalid request received. .github and .github.io show up in most orgs. They work fine today with an explicit .git in the remote, so this isn't a regression, but it's exactly the git-less form this PR is meant to enable.
Fix is to swap the order: the operation suffix is a protocol guarantee. Match the anchored /info/refs, /git-upload-pack or /git-receive-pack suffix against the end of the path, take the prefix as the repo path, and append .git only when it isn't already there, the same normalisation you're doing now, just reached first.
Ran it over the full matrix: fixes .github, user.github.io and the query-string case (…&foo=.git, which currently swallows the whole path into repoPath), and leaves every currently-working input identical. Worth anchoring PROXIED_URL_PATH_REGEX while you're in here too, byte-identical on everything that works today, and it kills a whole class of silent partial matches.