Parser for OpenAPI/Swagger specifications.
| 61 | |
| 62 | class OpenAPIParser: |
| 63 | """Parser for OpenAPI/Swagger specifications.""" |
| 64 | |
| 65 | def __init__(self): |
| 66 | self.logger = get_logger("apisec.parser") |
| 67 | |
| 68 | async def parse_url(self, url: str) -> ParsedAPI: |
| 69 | """Parse OpenAPI spec from URL. |
| 70 | |
| 71 | Args: |
| 72 | url: URL to OpenAPI JSON/YAML spec |
| 73 | |
| 74 | Returns: |
| 75 | Parsed API specification |
| 76 | """ |
| 77 | self.logger.info(f"Fetching OpenAPI spec from {url}") |
| 78 | |
| 79 | async with httpx.AsyncClient(timeout=30.0) as client: |
| 80 | response = await client.get(url) |
| 81 | response.raise_for_status() |
| 82 | |
| 83 | content_type = response.headers.get("content-type", "") |
| 84 | content = response.text |
| 85 | |
| 86 | if "yaml" in content_type or url.endswith((".yaml", ".yml")): |
| 87 | spec = yaml.safe_load(content) |
| 88 | else: |
| 89 | spec = json.loads(content) |
| 90 | |
| 91 | return self._parse_spec(spec, url) |
| 92 | |
| 93 | def parse_file(self, path: str) -> ParsedAPI: |
| 94 | """Parse OpenAPI spec from file. |
| 95 | |
| 96 | Args: |
| 97 | path: Path to OpenAPI JSON/YAML file |
| 98 | |
| 99 | Returns: |
| 100 | Parsed API specification |
| 101 | """ |
| 102 | file_path = Path(path) |
| 103 | self.logger.info(f"Parsing OpenAPI spec from {file_path}") |
| 104 | |
| 105 | content = file_path.read_text() |
| 106 | |
| 107 | if file_path.suffix in (".yaml", ".yml"): |
| 108 | spec = yaml.safe_load(content) |
| 109 | else: |
| 110 | spec = json.loads(content) |
| 111 | |
| 112 | return self._parse_spec(spec, str(file_path)) |
| 113 | |
| 114 | def parse_string(self, content: str, format: str = "json") -> ParsedAPI: |
| 115 | """Parse OpenAPI spec from string. |
| 116 | |
| 117 | Args: |
| 118 | content: OpenAPI spec content |
| 119 | format: "json" or "yaml" |
| 120 |
no outgoing calls
no test coverage detected