fix(hub): типы полей тела запроса дают 422, а не 500
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014Typ5sXWNMFirr2va2uL8o
This commit is contained in:
parent
34d5714898
commit
600163a9ee
@ -142,8 +142,12 @@ def h_note_put(hub, conn, m, q, body):
|
||||
|
||||
|
||||
def h_batches_post(hub, conn, m, q, body):
|
||||
if not body.get("title"):
|
||||
raise ApiError(422, "bad_batch", "нет title")
|
||||
if not body.get("title") or not isinstance(body["title"], str):
|
||||
raise ApiError(422, "bad_batch", "title — непустая строка")
|
||||
if not isinstance(body.get("author") or "api", str):
|
||||
raise ApiError(422, "bad_batch", "author — строка")
|
||||
if not isinstance(body.get("commands"), list):
|
||||
raise ApiError(422, "bad_batch", "commands — список команд")
|
||||
try:
|
||||
return 201, queue.create_batch(conn, body["title"], body.get("author") or "api", body.get("commands"))
|
||||
except CommandError as e:
|
||||
@ -166,6 +170,8 @@ def h_batch_cancel(hub, conn, m, q, body):
|
||||
|
||||
|
||||
def h_command_retry(hub, conn, m, q, body):
|
||||
if not isinstance(body.get("author") or "api", str):
|
||||
raise ApiError(422, "bad_retry", "author — строка")
|
||||
try:
|
||||
return 201, queue.retry_command(conn, _int(m), body.get("author") or "api")
|
||||
except KeyError:
|
||||
@ -184,12 +190,19 @@ def h_command_cancel(hub, conn, m, q, body):
|
||||
|
||||
|
||||
def h_refresh(hub, conn, m, q, body):
|
||||
if not isinstance(body.get("author") or "api", str):
|
||||
raise ApiError(422, "bad_refresh", "author — строка")
|
||||
keys = body.get("keys")
|
||||
if keys is not None and (not isinstance(keys, list) or not all(isinstance(k, str) and k for k in keys)):
|
||||
raise ApiError(422, "bad_refresh", "keys — список строк")
|
||||
if body.get("jql") is not None and not isinstance(body["jql"], str):
|
||||
raise ApiError(422, "bad_refresh", "jql — строка")
|
||||
if body.get("full"):
|
||||
params = {"jql": settings.get(conn, "base_jql")}
|
||||
elif body.get("jql"):
|
||||
params = {"jql": body["jql"]}
|
||||
elif body.get("keys"):
|
||||
params = {"keys": list(body["keys"])}
|
||||
params = {"keys": keys}
|
||||
else:
|
||||
raise ApiError(422, "bad_refresh", "нужно full, jql или keys")
|
||||
return 201, queue.create_batch(conn, "Обновление", body.get("author") or "api", [{"type": "refresh", "params": params}])
|
||||
@ -213,9 +226,12 @@ def h_settings_put(hub, conn, m, q, body):
|
||||
if bad:
|
||||
raise ApiError(422, "protected", ", ".join(bad))
|
||||
version = settings.get(conn, "settings_version")
|
||||
with db.transaction(conn):
|
||||
for key, value in body.items():
|
||||
version = settings.set_(conn, key, value)
|
||||
try:
|
||||
with db.transaction(conn):
|
||||
for key, value in body.items():
|
||||
version = settings.set_(conn, key, value)
|
||||
except ValueError as e: # запрет на защищённые ключи из settings.set_
|
||||
raise ApiError(422, "protected", str(e))
|
||||
return 200, {"settings_version": version}
|
||||
|
||||
|
||||
|
||||
@ -221,3 +221,23 @@ def test_claim_long_poll_times_out_with_null(hub):
|
||||
t0 = time.monotonic()
|
||||
assert hub["agent"].post("/agent/claim", {})["command"] is None
|
||||
assert 1.0 <= time.monotonic() - t0 < 4
|
||||
|
||||
|
||||
@pytest.mark.parametrize("path,body", [
|
||||
("/refresh", {"keys": 5}), ("/refresh", {"keys": "A-1"}), ("/refresh", {"keys": [1]}), ("/refresh", {"jql": 5}),
|
||||
("/batches", {"title": "x", "commands": 5}), ("/batches", {"title": "x", "commands": "x"}),
|
||||
("/batches", {"title": ["x"], "commands": []}), ("/batches", {"title": "x", "author": 5, "commands": []}),
|
||||
])
|
||||
def test_bad_body_shapes_are_422(hub, path, body):
|
||||
with pytest.raises(HubError) as e:
|
||||
hub["client"].post(path, body)
|
||||
assert e.value.status == 422
|
||||
|
||||
|
||||
def test_settings_put_invalid_is_4xx_and_atomic(hub):
|
||||
c = hub["client"]
|
||||
v0 = c.get("/settings")["settings_version"]
|
||||
with pytest.raises(HubError) as e:
|
||||
c.put("/settings", {"pacing": {"refresh": 3}, "tokens": {}})
|
||||
assert 400 <= e.value.status < 500
|
||||
assert c.get("/settings")["settings_version"] == v0
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user