-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhttp_client.py
More file actions
162 lines (130 loc) · 7.53 KB
/
Copy pathhttp_client.py
File metadata and controls
162 lines (130 loc) · 7.53 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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import json
import time
import requests
import urllib3
from requests.exceptions import Timeout, ConnectionError, SSLError, HTTPError, InvalidURL
from models import RequestData, ResponseData
from base64_utils import Base64_converter
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
class RequestWorker:
def __init__(self, request_data: RequestData, timeout: int = 30):
self.request_data = request_data
self.response_data = ResponseData()
self.timeout = timeout
def execute(self) -> ResponseData:
try:
url = self.request_data.url.strip()
if not url:
self.response_data.error = "Empty URL. Please enter a valid URL."
self.response_data.status_code = 0
return self.response_data
if not url.startswith(('http://', 'https://')):
url = 'https://' + url
headers = {
'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.9',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
for h in self.request_data.headers:
if h.enabled and h.key.strip():
headers[h.key.strip()] = h.value.strip()
params = {}
for p in self.request_data.params:
if p.enabled and p.key.strip():
params[p.key.strip()] = p.value.strip()
body = self.request_data.body.strip() if self.request_data.body else None
has_content_type = any(key.lower() == 'content-type' for key in headers)
if body and self.request_data.encode_base64:
try:
json.loads(body)
body = Base64_converter.encode_json_to_base64(body)
headers['Content-Type'] = 'text/plain'
except json.JSONDecodeError:
body = Base64_converter.encode(body)
headers['Content-Type'] = 'text/plain'
elif body and not has_content_type:
headers['Content-Type'] = self.request_data.body_content_type or 'application/json'
start_time = time.time()
json_data = None
should_send_json = False
content_type = headers.get('Content-Type', '').lower()
if body and not self.request_data.encode_base64 and 'json' in content_type:
try:
json_data = json.loads(body)
should_send_json = True
except json.JSONDecodeError:
json_data = None
response = requests.request(
method=self.request_data.method.value,
url=url,
headers=headers,
params=params,
json=json_data if should_send_json else None,
data=body if body and not should_send_json else None,
verify=False,
timeout=self.timeout
)
elapsed_time = (time.time() - start_time) * 1000
self.response_data.status_code = response.status_code
self.response_data.elapsed_time = elapsed_time
self.response_data.headers = dict(response.headers)
response_text = response.text
if response_text and self.request_data.decode_base64:
try:
if Base64_converter.is_valid_base64(response_text):
response_text = Base64_converter.decode_base64_to_json_orjson(response_text, pretty=True)
except Exception:
try:
response_text = Base64_converter.decode(response_text)
except Exception:
pass
try:
formatted_body = json.dumps(json.loads(response_text), indent=2)
except json.JSONDecodeError:
formatted_body = response_text
self.response_data.body = formatted_body
except Timeout as e:
self.response_data.error = f"Timeout: The request took longer than {self.timeout} seconds. The server may be slow or unresponsive."
self.response_data.status_code = 0
self.response_data.body = f"Request Timeout\n\nThe request timed out after {self.timeout} seconds.\n\nPossible reasons:\n• Server is taking too long to respond\n• Network connection is slow\n• Server is temporarily unavailable\n\nTry again with a longer timeout or check your internet connection."
except ConnectionError as e:
error_msg = str(e)
if "Connection refused" in error_msg:
self.response_data.error = "Connection Refused: The server refused the connection."
self.response_data.body = f"Connection Refused\n\nThe server actively refused the connection.\n\nPossible reasons:\n• Server is not running\n• Wrong port number\n• Firewall blocking the connection\n• Server requires authentication"
elif "Name or service not known" in error_msg:
self.response_data.error = "DNS Error: Could not resolve the hostname."
self.response_data.body = f"DNS Error\n\nCould not resolve the domain name.\n\nPossible reasons:\n• Typo in the URL\n• Domain name doesn't exist\n• No internet connection\n• DNS server is unreachable"
else:
self.response_data.error = f"Connection Error: {error_msg}"
self.response_data.body = f"Connection Error\n\n{error_msg}\n\nCheck the URL and your internet connection."
self.response_data.status_code = 0
except SSLError as e:
self.response_data.error = "SSL Error: Failed to verify the SSL certificate."
self.response_data.body = f"SSL Certificate Error\n\nThe SSL certificate verification failed.\n\nThis usually happens when:\n• The server's SSL certificate is self-signed\n• The certificate has expired\n• The certificate doesn't match the domain\n\nIn development, you can bypass this by disabling SSL verification."
except InvalidURL as e:
self.response_data.error = "Invalid URL: Please check the URL format."
self.response_data.body = f"Invalid URL\n\nThe URL format appears to be invalid.\n\nPlease check:\n• No special characters in URL\n• Proper domain format\n• No missing slashes"
except HTTPError as e:
self.response_data.error = f"HTTP Error: {str(e)}"
self.response_data.body = f"HTTP Error\n\n{str(e)}"
except json.JSONDecodeError as e:
self.response_data.error = "Invalid JSON in request body."
self.response_data.body = f"JSON Parse Error\n\nThe request body contains invalid JSON.\n\nError: {str(e)}"
except requests.exceptions.RequestException as e:
self.response_data.error = f"Request Error: {str(e)}"
self.response_data.body = f"Request Error\n\n{str(e)}"
except Exception as e:
self.response_data.error = f"Unexpected Error: {str(e)}"
self.response_data.body = f"An unexpected error occurred.\n\nError: {str(e)}\n\nPlease try again or check the URL."
return self.response_data
def get_timeout_options():
"""Return available timeout options"""
return [
("5 seconds", 5),
("10 seconds", 10),
("30 seconds", 30),
("60 seconds", 60),
("120 seconds", 120),
("300 seconds", 300),
]