Re-upload: CI infrastructure issue resolved, all tests verified passing
This commit is contained in:
142
http_log_explorer/models/http_entry.py
Normal file
142
http_log_explorer/models/http_entry.py
Normal file
@@ -0,0 +1,142 @@
|
||||
"""Data models for HTTP entries."""
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
|
||||
|
||||
@dataclass
|
||||
class Request:
|
||||
"""Represents an HTTP request."""
|
||||
|
||||
method: str
|
||||
url: str
|
||||
http_version: str = "HTTP/1.1"
|
||||
headers: dict[str, str] = field(default_factory=dict)
|
||||
body: str | None = None
|
||||
query_params: dict[str, str] = field(default_factory=dict)
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
if isinstance(self.headers, list):
|
||||
self.headers = {h.get("name", ""): h.get("value", "") for h in self.headers}
|
||||
|
||||
|
||||
@dataclass
|
||||
class Response:
|
||||
"""Represents an HTTP response."""
|
||||
|
||||
status: int
|
||||
status_text: str
|
||||
http_version: str = "HTTP/1.1"
|
||||
headers: dict[str, str] = field(default_factory=dict)
|
||||
body: str | None = None
|
||||
content_type: str | None = None
|
||||
response_time_ms: float | None = None
|
||||
|
||||
def __post_init__(self) -> None:
|
||||
if isinstance(self.headers, list):
|
||||
self.headers = {h.get("name", ""): h.get("value", "") for h in self.headers}
|
||||
|
||||
|
||||
@dataclass
|
||||
class HTTPEntry:
|
||||
"""Represents a complete HTTP request/response pair."""
|
||||
|
||||
id: str
|
||||
request: Request
|
||||
response: Response
|
||||
timestamp: datetime | None = None
|
||||
server_ip: str | None = None
|
||||
connection: str | None = None
|
||||
raw_size: int | None = None
|
||||
source_file: str | None = None
|
||||
|
||||
@property
|
||||
def duration_ms(self) -> float | None:
|
||||
"""Get response time in milliseconds."""
|
||||
return self.response.response_time_ms
|
||||
|
||||
@property
|
||||
def content_type(self) -> str | None:
|
||||
"""Get content type from response headers."""
|
||||
if self.response.content_type:
|
||||
return self.response.content_type
|
||||
for key, value in self.response.headers.items():
|
||||
if key.lower() == "content-type":
|
||||
return value
|
||||
return None
|
||||
|
||||
@property
|
||||
def endpoint(self) -> str:
|
||||
"""Extract endpoint path from URL."""
|
||||
from urllib.parse import urlparse
|
||||
|
||||
parsed = urlparse(self.request.url)
|
||||
return parsed.path or "/"
|
||||
|
||||
@property
|
||||
def host(self) -> str:
|
||||
"""Extract host from URL."""
|
||||
from urllib.parse import urlparse
|
||||
|
||||
parsed = urlparse(self.request.url)
|
||||
return parsed.netloc
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
"""Convert to dictionary representation."""
|
||||
return {
|
||||
"id": self.id,
|
||||
"request": {
|
||||
"method": self.request.method,
|
||||
"url": self.request.url,
|
||||
"http_version": self.request.http_version,
|
||||
"headers": self.request.headers,
|
||||
"body": self.request.body,
|
||||
"query_params": self.request.query_params,
|
||||
},
|
||||
"response": {
|
||||
"status": self.response.status,
|
||||
"status_text": self.response.status_text,
|
||||
"http_version": self.response.http_version,
|
||||
"headers": self.response.headers,
|
||||
"body": self.response.body,
|
||||
"content_type": self.response.content_type,
|
||||
"response_time_ms": self.response.response_time_ms,
|
||||
},
|
||||
"timestamp": self.timestamp.isoformat() if self.timestamp else None,
|
||||
"server_ip": self.server_ip,
|
||||
"connection": self.connection,
|
||||
"raw_size": self.raw_size,
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class FilterCriteria:
|
||||
"""Criteria for filtering HTTP entries."""
|
||||
|
||||
methods: list[str] | None = None
|
||||
status_codes: list[int] | None = None
|
||||
url_pattern: str | None = None
|
||||
content_types: list[str] | None = None
|
||||
start_time: datetime | None = None
|
||||
end_time: datetime | None = None
|
||||
min_response_time_ms: float | None = None
|
||||
max_response_time_ms: float | None = None
|
||||
request_body_contains: str | None = None
|
||||
response_body_contains: str | None = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class DiffResult:
|
||||
"""Represents the result of comparing two HTTP entries."""
|
||||
|
||||
entry1_id: str
|
||||
entry2_id: str
|
||||
request_headers_diff: list[str] = field(default_factory=list)
|
||||
request_body_diff: list[str] = field(default_factory=list)
|
||||
response_headers_diff: list[str] = field(default_factory=list)
|
||||
response_body_diff: list[str] = field(default_factory=list)
|
||||
status_changed: bool = False
|
||||
status1: int = 0
|
||||
status2: int = 0
|
||||
url_changed: bool = False
|
||||
Reference in New Issue
Block a user