(schema: Dict, only_one_path_and_method: bool)
| 19 | |
| 20 | |
| 21 | def validate_openapi_schema(schema: Dict, only_one_path_and_method: bool): |
| 22 | try: |
| 23 | openapi_spec_validator.validate(schema) |
| 24 | # check exactly one server in the schema |
| 25 | except Exception as e: |
| 26 | if hasattr(e, "message"): |
| 27 | raise_http_error(ErrorCode.REQUEST_VALIDATION_ERROR, message=f"Invalid openapi schema: {e.message}") |
| 28 | else: |
| 29 | raise_http_error(ErrorCode.REQUEST_VALIDATION_ERROR, message=f"Invalid openapi schema: {e}") |
| 30 | |
| 31 | if "servers" not in schema: |
| 32 | raise_http_error(ErrorCode.REQUEST_VALIDATION_ERROR, message="No server is found in action schema") |
| 33 | |
| 34 | if "paths" not in schema: |
| 35 | raise_http_error(ErrorCode.REQUEST_VALIDATION_ERROR, message="No paths is found in action schema") |
| 36 | |
| 37 | if len(schema["servers"]) != 1: |
| 38 | raise_http_error(ErrorCode.REQUEST_VALIDATION_ERROR, message="Exactly one server is allowed in action schema") |
| 39 | |
| 40 | if only_one_path_and_method: |
| 41 | if len(schema["paths"]) != 1: |
| 42 | raise_http_error(ErrorCode.REQUEST_VALIDATION_ERROR, message="Only one path is allowed in action schema") |
| 43 | path = list(schema["paths"].keys())[0] |
| 44 | if len(schema["paths"][path]) != 1: |
| 45 | raise_http_error(ErrorCode.REQUEST_VALIDATION_ERROR, message="Only one method is allowed in action schema") |
| 46 | |
| 47 | # check each path method has a valid description and operationId |
| 48 | for path, methods in schema["paths"].items(): |
| 49 | for method, details in methods.items(): |
| 50 | if not details.get("description") or not isinstance(details["description"], str): |
| 51 | if details.get("summary") and isinstance(details["summary"], str): |
| 52 | # use summary as its description |
| 53 | details["description"] = details["summary"] |
| 54 | else: |
| 55 | raise_http_error( |
| 56 | ErrorCode.REQUEST_VALIDATION_ERROR, |
| 57 | message=f"No description is found in {method} {path} in action schema", |
| 58 | ) |
| 59 | if len(details["description"]) > 512: |
| 60 | raise_http_error( |
| 61 | ErrorCode.REQUEST_VALIDATION_ERROR, |
| 62 | message=f"Description cannot be longer than 512 characters in {method} {path} in action schema", |
| 63 | ) |
| 64 | |
| 65 | if not details.get("operationId") or not isinstance(details["operationId"], str): |
| 66 | raise_http_error( |
| 67 | ErrorCode.REQUEST_VALIDATION_ERROR, |
| 68 | message=f"No operationId is found in {method} {path} in action schema", |
| 69 | ) |
| 70 | if len(details["operationId"]) > 128: |
| 71 | raise_http_error( |
| 72 | ErrorCode.REQUEST_VALIDATION_ERROR, |
| 73 | message=f"operationId cannot be longer than 128 characters in {method} {path} in action schema", |
| 74 | ) |
| 75 | |
| 76 | if not re.match(r"^[a-zA-Z_][a-zA-Z0-9_]*$", details["operationId"]): |
| 77 | raise_http_error( |
| 78 | ErrorCode.REQUEST_VALIDATION_ERROR, |
no test coverage detected