roster/src/models.py
Pavel Baksy b19af25569 Initial commit: Roster HTTP client for GNOME
Roster is a modern HTTP client application for GNOME, similar to Postman,
built with GTK 4 and libadwaita.

Features:
- Send HTTP requests (GET, POST, PUT, DELETE)
- Configure custom headers with add/remove functionality
- Request body editor for POST/PUT/DELETE requests
- View response headers and bodies in separate tabs
- Track request history with JSON persistence
- Load previous requests from history with confirmation dialog
- Beautiful GNOME-native UI with libadwaita components
- HTTPie backend for reliable HTTP communication

Technical implementation:
- Python 3 with GTK 4 and libadwaita 1
- Meson build system with Flatpak support
- Custom widgets (HeaderRow, HistoryItem) with GObject signals
- Background threading for non-blocking HTTP requests
- AdwTabView for modern tabbed interface
- History persistence to ~/.config/roster/history.json
- Comprehensive error handling and user feedback
2025-12-18 11:05:33 +01:00

87 lines
2.6 KiB
Python

# models.py
#
# Copyright 2025 Pavel Baksy
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# SPDX-License-Identifier: GPL-3.0-or-later
from dataclasses import dataclass, asdict
from typing import Dict, Optional
@dataclass
class HttpRequest:
"""Represents an HTTP request."""
method: str # "GET", "POST", "PUT", "DELETE"
url: str
headers: Dict[str, str] # Key-value pairs
body: str # Raw text body
def to_dict(self):
"""Convert to dictionary for JSON serialization."""
return asdict(self)
@classmethod
def from_dict(cls, data):
"""Create instance from dictionary."""
return cls(**data)
@dataclass
class HttpResponse:
"""Represents an HTTP response."""
status_code: int
status_text: str # e.g., "OK"
headers: str # Raw header text from HTTPie
body: str # Raw body text
response_time_ms: float
def to_dict(self):
"""Convert to dictionary for JSON serialization."""
return asdict(self)
@classmethod
def from_dict(cls, data):
"""Create instance from dictionary."""
return cls(**data)
@dataclass
class HistoryEntry:
"""Represents a request/response pair in history."""
timestamp: str # ISO format datetime
request: HttpRequest
response: Optional[HttpResponse]
error: Optional[str] # Error message if request failed
def to_dict(self):
"""Convert to dictionary for JSON serialization."""
return {
'timestamp': self.timestamp,
'request': self.request.to_dict(),
'response': self.response.to_dict() if self.response else None,
'error': self.error
}
@classmethod
def from_dict(cls, data):
"""Create instance from dictionary."""
return cls(
timestamp=data['timestamp'],
request=HttpRequest.from_dict(data['request']),
response=HttpResponse.from_dict(data['response']) if data.get('response') else None,
error=data.get('error')
)