Skip to content

Commit 803db24

Browse files
Merge pull request #1234 from Aiven-Open/mbasani-fix-schema-request
Fix schema config for extra fields
2 parents 07d7b00 + 0e363e0 commit 803db24

3 files changed

Lines changed: 67 additions & 19 deletions

File tree

src/karapace/api/routers/requests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class SchemaRequest(BaseModel):
2222
references: list[SchemaReference] | None = None
2323
metadata: Any | None = None
2424
ruleSet: Any | None = None
25-
model_config = ConfigDict(extra="forbid")
25+
model_config = ConfigDict(extra="ignore")
2626

2727
@field_validator("schema_str")
2828
@classmethod

tests/integration/test_schema.py

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2168,7 +2168,7 @@ async def test_schema_body_validation(registry_async_client: Client) -> None:
21682168
subject = create_subject_name_factory("test_schema_body_validation")()
21692169
post_functions = {registry_async_client.post_subjects, registry_async_client.post_subjects_versions}
21702170
for function in post_functions:
2171-
# Wrong field name
2171+
# Wrong field name (required field "schema" is still missing)
21722172
res = await function(subject=subject, json={"invalid_field": "invalid_value"})
21732173
assert res.status_code == 422
21742174
assert res.json()["error_code"] == 422
@@ -2179,25 +2179,10 @@ async def test_schema_body_validation(registry_async_client: Client) -> None:
21792179
"msg": "Field required",
21802180
"input": {"invalid_field": "invalid_value"},
21812181
},
2182-
{
2183-
"type": "extra_forbidden",
2184-
"loc": ["body", "invalid_field"],
2185-
"msg": "Extra inputs are not permitted",
2186-
"input": "invalid_value",
2187-
},
21882182
]
2189-
# Additional field
2183+
# Additional field (extra fields are ignored to match v4 behavior)
21902184
res = await function(subject=subject, json={"schema": '{"type": "string"}', "invalid_field": "invalid_value"})
2191-
assert res.status_code == 422
2192-
assert res.json()["error_code"] == 422
2193-
assert res.json()["message"] == [
2194-
{
2195-
"type": "extra_forbidden",
2196-
"loc": ["body", "invalid_field"],
2197-
"msg": "Extra inputs are not permitted",
2198-
"input": "invalid_value",
2199-
},
2200-
]
2185+
assert res.ok
22012186
# Invalid body type
22022187
res = await function(subject=subject, json="invalid")
22032188
assert res.status_code == 422

tests/unit/api/test_requests.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"""
2+
karapace - unit tests for request models
3+
4+
Copyright (c) 2025 Aiven Ltd
5+
See LICENSE for details
6+
"""
7+
8+
import pytest
9+
from pydantic import ValidationError
10+
11+
from karapace.api.routers.requests import SchemaRequest
12+
13+
14+
class TestSchemaRequestExtraFields:
15+
"""Extra fields must be silently ignored to match v4 behavior.
16+
17+
v4 parsed the request body as a plain dict and only read the keys it
18+
needed. The 5.x Pydantic model must not reject unknown keys so that
19+
existing clients that send extra properties (e.g. ``compatibility``)
20+
continue to work after upgrading.
21+
"""
22+
23+
def test_extra_fields_are_ignored(self) -> None:
24+
req = SchemaRequest.model_validate(
25+
{
26+
"schema": '{"type": "string"}',
27+
"compatibility": "BACKWARD",
28+
}
29+
)
30+
assert req.schema_str == '{"type": "string"}'
31+
assert not hasattr(req, "compatibility")
32+
33+
def test_multiple_extra_fields_are_ignored(self) -> None:
34+
req = SchemaRequest.model_validate(
35+
{
36+
"schema": '{"type": "string"}',
37+
"compatibility": "BACKWARD",
38+
"unknown_prop": 123,
39+
"another": True,
40+
}
41+
)
42+
assert req.schema_str == '{"type": "string"}'
43+
44+
def test_required_field_still_validated(self) -> None:
45+
with pytest.raises(ValidationError) as exc_info:
46+
SchemaRequest.model_validate(
47+
{
48+
"compatibility": "BACKWARD",
49+
}
50+
)
51+
errors = exc_info.value.errors()
52+
assert any(e["type"] == "missing" for e in errors)
53+
54+
def test_valid_request_with_all_fields(self) -> None:
55+
req = SchemaRequest.model_validate(
56+
{
57+
"schema": '{"type": "string"}',
58+
"schemaType": "AVRO",
59+
"references": None,
60+
}
61+
)
62+
assert req.schema_str == '{"type": "string"}'
63+
assert req.schema_type.value == "AVRO"

0 commit comments

Comments
 (0)