dev → main: rule-arm review, moment usage by rule, no-subject auto-inject, copy check, S3 test wording #215
@@ -120,6 +120,12 @@ def _says(response: httpx.Response) -> str:
|
||||
"AccessDenied": "the key isn't allowed to do that",
|
||||
}
|
||||
said = hints.get(code) or message or response.reason_phrase
|
||||
if not code and 400 <= response.status_code < 500:
|
||||
# S3 refuses with an <Error><Code> body. A 4xx without one came from
|
||||
# something else at that address — most often a web server on the
|
||||
# default port, when the S3 service listens on a port of its own.
|
||||
said = ("the address answered, but not as S3 — check the scheme and "
|
||||
"the port (an S3 service usually listens on its own port)")
|
||||
return f"HTTP {response.status_code}{f' {code}' if code else ''}: {said}."
|
||||
|
||||
|
||||
|
||||
@@ -78,6 +78,22 @@ def test_a_refusal_says_why(tmp_path):
|
||||
asyncio.run(s3.put_file(TARGET, "b.tar", f, transport=transport))
|
||||
|
||||
|
||||
def test_a_web_server_at_the_address_is_named_as_not_s3():
|
||||
"""No port in the address: the request lands on whatever serves port 80,
|
||||
and its plain 404 says nothing about S3."""
|
||||
page = b"<html><body><h1>404 Not Found</h1></body></html>"
|
||||
transport = httpx.MockTransport(lambda r: httpx.Response(404, content=page))
|
||||
with pytest.raises(s3.S3Error, match=r"HTTP 404: the address answered, but not as S3 — check the scheme and the port"):
|
||||
asyncio.run(s3.list_objects(TARGET, transport=transport))
|
||||
|
||||
|
||||
def test_a_server_error_without_a_body_is_not_blamed_on_the_port():
|
||||
transport = httpx.MockTransport(lambda r: httpx.Response(503))
|
||||
with pytest.raises(s3.S3Error, match="HTTP 503: Service Unavailable") as err:
|
||||
asyncio.run(s3.list_objects(TARGET, transport=transport))
|
||||
assert "port" not in str(err.value)
|
||||
|
||||
|
||||
def test_unreachable_says_so(tmp_path):
|
||||
f = tmp_path / "b.tar"
|
||||
f.write_bytes(b"x")
|
||||
|
||||
Reference in New Issue
Block a user