patx/hglab
make auth work better with git-remote-hg
Commit 96b69e7f56c1 · Harrison Erd · 2026-05-05 02:49 -0400
Comments
No comments yet.
Diff
diff --git a/app.py b/app.py
--- a/app.py
+++ b/app.py
@@ -552,11 +552,14 @@
AUTH_FAILURES.pop(auth_rate_key(kind, identifier), None)
-def too_many_requests_response():
+def too_many_requests_response(close_connection=False):
+ headers = {"Retry-After": str(RATE_LIMIT_COOLDOWN_SECONDS)}
+ if close_connection:
+ headers["Connection"] = "close"
return HTTPResponse(
"Too many failed attempts. Try again later.\n",
status=429,
- headers={"Retry-After": str(RATE_LIMIT_COOLDOWN_SECONDS)},
+ headers=headers,
content_type="text/plain; charset=utf-8",
)
@@ -2471,7 +2474,7 @@
return HTTPResponse(
message + "\n",
status=401,
- headers={"WWW-Authenticate": 'Basic realm="HgHost"'},
+ headers={"WWW-Authenticate": 'Basic realm="HgHost"', "Connection": "close"},
content_type="text/plain; charset=utf-8",
)
@@ -3291,14 +3294,19 @@
auth_user, auth_error = parse_basic_auth("hg" if is_write else None, clear_on_success=not is_write)
if is_write:
if auth_error == "rate_limited":
- return too_many_requests_response()
+ return too_many_requests_response(close_connection=True)
if auth_error:
return basic_auth_challenge("Invalid Mercurial credentials.")
if not auth_user:
return basic_auth_challenge()
if not user_can_maintain_repo(auth_user, repo):
record_auth_failure("hg", auth_user["username"])
- return HTTPResponse("Push not authorized for this repository.\n", status=403, content_type="text/plain")
+ return HTTPResponse(
+ "Push not authorized for this repository.\n",
+ status=403,
+ headers={"Connection": "close"},
+ content_type="text/plain; charset=utf-8",
+ )
clear_auth_failures("hg", auth_user["username"])
return hg_wsgi_response(repo, auth_user)
diff --git a/tests/test_app.py b/tests/test_app.py
--- a/tests/test_app.py
+++ b/tests/test_app.py
@@ -356,6 +356,7 @@
response = client.post("/hg/alice/demo?cmd=unbundle")
assert response.status_code == 401
assert response.header("WWW-Authenticate") == 'Basic realm="HgHost"'
+ assert response.header("Connection") == "close"
def test_browser_form_size_limit(isolated_app, monkeypatch):
@@ -388,8 +389,10 @@
for _ in range(2):
response = client.post("/hg/alice/demo?cmd=unbundle", headers=basic_auth("alice", "wrong"))
assert response.status_code == 401
+ assert response.header("Connection") == "close"
response = client.post("/hg/alice/demo?cmd=unbundle", headers=basic_auth("alice", "wrong"))
assert response.status_code == 429
+ assert response.header("Connection") == "close"
def test_readme_and_file_previews_are_truncated(isolated_app, monkeypatch):
@@ -1118,12 +1121,15 @@
response = client.post("/hg/alice/demo?cmd=unbundle")
assert response.status_code == 401
assert response.header("WWW-Authenticate") == 'Basic realm="HgHost"'
+ assert response.header("Connection") == "close"
assert "Authentication required." in response.text
response = client.post("/hg/alice/demo?cmd=unbundle", headers=basic_auth("alice", "wrong"))
assert response.status_code == 401
+ assert response.header("Connection") == "close"
assert "Invalid Mercurial credentials." in response.text
response = client.post("/hg/alice/demo?cmd=unbundle", headers=basic_auth("bob", "bob-password"))
assert response.status_code == 403
+ assert response.header("Connection") == "close"
assert "Push not authorized" in response.text