fix(discovery): correct criminalip, hudsonrock, mojeek, githubcode error handling

- criminalip: inspect HTTP status via provider_http_error instead of
  only the provider's embedded status field, so 401/403/429 with
  non-JSON bodies are classified correctly; build the scan request with
  json_body instead of an f-string that produced invalid JSON for
  targets containing quotes or backslashes
- hudsonrock: remove the dead transport-error retry loop (the shared
  transport already swallows those exceptions and returns None), drop a
  redundant isinstance check, and describe the real 429-only retry
- mojeek: fix the finite API path off-by-one that fetched zero pages
  for --limit 1 and dropped the final partial page, and request pages
  sequentially instead of one concurrent burst
- githubcode: only HTTP 429 responses retry; a 403 now fails
  immediately as access-denied instead of stalling ~3 minutes and being
  mislabeled rate-limited
This commit is contained in:
L1ghtn1ng
2026-09-17 01:38:23 +01:00
parent 4f60fc9e8b
commit 2ee9b557e5
7 changed files with 235 additions and 104 deletions
@@ -323,4 +323,40 @@ async def test_github_code_cancellation_propagates(monkeypatch: pytest.MonkeyPat
await search.process()
@pytest.mark.asyncio
async def test_github_code_forbidden_fails_immediately_as_access_denied(install_github_responses) -> None:
class ForbiddenResponse(FakeResponse):
status = 403
requested_urls = install_github_responses(ForbiddenResponse({}, {}))
search = githubcode.SearchGithubCode('example.com', limit=None)
report = await search.process()
assert len(requested_urls) == 1
assert report == githubcode.SourceExecutionReport('failed', 'access-denied')
@pytest.mark.asyncio
async def test_github_code_rate_limited_retries_then_reports(
install_github_responses,
monkeypatch: pytest.MonkeyPatch,
) -> None:
class TooManyRequestsResponse(FakeResponse):
status = 429
requested_urls = install_github_responses(*(TooManyRequestsResponse({}, {}) for _ in range(4)))
async def no_sleep(_delay: float) -> None:
return None
monkeypatch.setattr(githubcode.asyncio, 'sleep', no_sleep)
search = githubcode.SearchGithubCode('example.com', limit=None)
report = await search.process()
assert len(requested_urls) == 4
assert report == githubcode.SourceExecutionReport('rate-limited', 'rate-limited')
pytestmark = pytest.mark.provider_contract('github-code')