openapi: Switch to new openapi_core validation API.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2023-07-10 14:23:27 -04:00 committed by Tim Abbott
parent 60ce5e1955
commit 9bb3d15a79
1 changed files with 20 additions and 24 deletions

View File

@ -10,8 +10,9 @@ import os
import re import re
from typing import Any, Dict, List, Mapping, Optional, Set, Tuple, Union, cast from typing import Any, Dict, List, Mapping, Optional, Set, Tuple, Union, cast
import openapi_core
import orjson import orjson
from openapi_core import Spec, openapi_request_validator, openapi_response_validator from openapi_core import Spec
from openapi_core.protocols import Response from openapi_core.protocols import Response
from openapi_core.testing import MockRequest, MockResponse from openapi_core.testing import MockRequest, MockResponse
from openapi_core.validation.exceptions import ValidationError as OpenAPIValidationError from openapi_core.validation.exceptions import ValidationError as OpenAPIValidationError
@ -413,11 +414,10 @@ def validate_against_openapi_schema(
orjson.dumps(content).decode(), orjson.dumps(content).decode(),
status_code=int(status_code), status_code=int(status_code),
) )
result = openapi_response_validator.validate(
openapi_spec.spec(), mock_request, cast(Response, mock_response)
)
try: try:
result.raise_for_errors() openapi_core.validate_response(
mock_request, cast(Response, mock_response), spec=openapi_spec.spec()
)
except OpenAPIValidationError as error: except OpenAPIValidationError as error:
message = f"Response validation error at {method} /api/v1{path} ({status_code}):" message = f"Response validation error at {method} /api/v1{path} ({status_code}):"
message += f"\n\n{type(error).__name__}: {error}" message += f"\n\n{type(error).__name__}: {error}"
@ -497,19 +497,6 @@ def validate_request(
if url == "/user_uploads" or url.startswith("/realm/emoji/"): if url == "/user_uploads" or url.startswith("/realm/emoji/"):
return return
# Now using the openapi_core APIs, validate the request schema
# against the OpenAPI documentation.
assert isinstance(data, dict)
mock_request = MockRequest(
"http://localhost:9991/", method, "/api/v1" + url, headers=http_headers, args=data
)
result = openapi_request_validator.validate(openapi_spec.spec(), mock_request)
errors = list(result.errors)
# If no errors are raised, then validation is successful
if not errors:
return
# Requests that do not validate against the OpenAPI spec must either: # Requests that do not validate against the OpenAPI spec must either:
# * Have returned a 400 (bad request) error # * Have returned a 400 (bad request) error
# * Have returned a 200 (success) with this request marked as intentionally # * Have returned a 200 (success) with this request marked as intentionally
@ -519,8 +506,17 @@ def validate_request(
if status_code.startswith("2") and intentionally_undocumented: if status_code.startswith("2") and intentionally_undocumented:
return return
# Show a block error message explaining the options for fixing it. # Now using the openapi_core APIs, validate the request schema
msg = f""" # against the OpenAPI documentation.
assert isinstance(data, dict)
mock_request = MockRequest(
"http://localhost:9991/", method, "/api/v1" + url, headers=http_headers, args=data
)
try:
openapi_core.validate_request(mock_request, spec=openapi_spec.spec())
except OpenAPIValidationError as error:
# Show a block error message explaining the options for fixing it.
msg = f"""
Error! The OpenAPI schema for {method} {url} is not consistent Error! The OpenAPI schema for {method} {url} is not consistent
with the parameters passed in this HTTP request. Consider: with the parameters passed in this HTTP request. Consider:
@ -533,7 +529,7 @@ with the parameters passed in this HTTP request. Consider:
See https://zulip.readthedocs.io/en/latest/documentation/api.html for help. See https://zulip.readthedocs.io/en/latest/documentation/api.html for help.
The errors logged by the OpenAPI validator are below:\n""" The error logged by the OpenAPI validator is below:
for error in errors: {error}
msg += f"* {error}\n" """
raise SchemaError(msg) raise SchemaError(msg)