-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathresponse.py
More file actions
99 lines (82 loc) · 3.52 KB
/
Copy pathresponse.py
File metadata and controls
99 lines (82 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
from datetime import datetime
import json
class Response:
"""
HTTP Response class that handles creating and formatting HTTP responses
according to RFC 7231 specifications
"""
def __init__(self, version='1.1', status=200, message='OK'):
self.status = status
self.message = message
self.version = version
self.headers = {}
self.body = ""
self.binary_data = None
# Set default headers
self._set_default_headers()
def _set_default_headers(self):
"""Set default HTTP headers for all responses"""
self.headers['Date'] = datetime.utcnow().strftime('%a, %d %b %Y %H:%M:%S GMT')
self.headers['Server'] = 'Multi-threaded HTTP Server'
self.headers['Connection'] = 'keep-alive'
self.headers['Keep-Alive'] = 'timeout=30, max=100'
def __str__(self) -> str:
"""
Convert response to HTTP string format
Returns the complete HTTP response as a string
"""
# Create status line
response_line = f'HTTP/{self.version} {self.status} {self.message}'
# Format headers
header_lines = []
for key, value in self.headers.items():
header_lines.append(f'{key}: {value}')
# Join response line and headers
response = response_line + '\r\n' + '\r\n'.join(header_lines) + '\r\n\r\n'
# Add body if it exists
if self.body:
response += self.body
return response
def to_bytes(self) -> bytes:
"""
Convert response to bytes format for binary data transmission
"""
# Create status line and headers as string
response_line = f'HTTP/{self.version} {self.status} {self.message}'
header_lines = []
for key, value in self.headers.items():
header_lines.append(f'{key}: {value}')
headers_str = response_line + '\r\n' + '\r\n'.join(header_lines) + '\r\n\r\n'
headers_bytes = headers_str.encode('utf-8')
# Add binary data if it exists
if self.binary_data is not None:
return headers_bytes + self.binary_data
elif self.body:
return headers_bytes + self.body.encode('utf-8')
else:
return headers_bytes
def add_header(self, key: str, value: str) -> None:
"""Add a header to the response"""
self.headers[key] = value
def set_body(self, data: str):
"""Set text body data and Content-Length header"""
self.body = data
self.headers['Content-Length'] = str(len(data.encode('utf-8')))
def set_binary_data(self, data: bytes):
"""Set binary body data and Content-Length header"""
self.binary_data = data
self.headers['Content-Length'] = str(len(data))
def set_json_body(self, data: dict):
"""Set JSON body data with appropriate headers"""
json_str = json.dumps(data)
self.set_body(json_str)
self.add_header('Content-Type', 'application/json')
def set_html_body(self, html: str):
"""Set HTML body data with appropriate headers"""
self.set_body(html)
self.add_header('Content-Type', 'text/html; charset=utf-8')
def set_file_download(self, filename: str, data: bytes):
"""Set response for file download with appropriate headers"""
self.set_binary_data(data)
self.add_header('Content-Type', 'application/octet-stream')
self.add_header('Content-Disposition', f'attachment; filename="{filename}"')