pyproxytools 0.4.0__tar.gz → 0.4.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyproxytools-0.4.0/pyproxytools.egg-info → pyproxytools-0.4.2}/PKG-INFO +5 -5
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/README.md +3 -4
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxy/__init__.py +1 -1
- pyproxytools-0.4.2/pyproxy/__main__.py +4 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxy/handlers/client.py +30 -43
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxy/handlers/http.py +99 -53
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxy/handlers/https.py +172 -137
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxy/pyproxy.py +47 -32
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxy/server.py +73 -47
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxy/utils/args.py +1 -1
- pyproxytools-0.4.2/pyproxy/utils/config.py +100 -0
- pyproxytools-0.4.2/pyproxy/utils/http_req.py +24 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxy/utils/logger.py +19 -4
- {pyproxytools-0.4.0 → pyproxytools-0.4.2/pyproxytools.egg-info}/PKG-INFO +5 -5
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxytools.egg-info/SOURCES.txt +1 -1
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxytools.egg-info/requires.txt +1 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/requirements.txt +2 -1
- pyproxytools-0.4.2/tests/utils/test_http_req.py +39 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/tests/utils/test_logger.py +10 -1
- pyproxytools-0.4.0/pyproxy/utils/config.py +0 -110
- pyproxytools-0.4.0/pyproxy/utils/http_req.py +0 -53
- pyproxytools-0.4.0/pyproxy/utils/version.py +0 -0
- pyproxytools-0.4.0/tests/utils/test_http_req.py +0 -69
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/LICENSE +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/benchmark/benchmark.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/benchmark/utils/__init__.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/benchmark/utils/html.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/benchmark/utils/req.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproject.toml +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxy/handlers/__init__.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxy/modules/__init__.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxy/modules/cancel_inspect.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxy/modules/custom_header.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxy/modules/filter.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxy/modules/shortcuts.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxy/monitoring/__init__.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxy/monitoring/web.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxy/utils/__init__.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxy/utils/crypto.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxytools.egg-info/dependency_links.txt +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxytools.egg-info/entry_points.txt +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/pyproxytools.egg-info/top_level.txt +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/setup.cfg +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/setup.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/tests/modules/__init__.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/tests/modules/test_cancel_inspect.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/tests/modules/test_custom_header.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/tests/modules/test_filter.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/tests/modules/test_shortcuts.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/tests/utils/__init__.py +0 -0
- {pyproxytools-0.4.0 → pyproxytools-0.4.2}/tests/utils/test_crypto.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyproxytools
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Lightweight and fast python web proxy
|
|
5
5
|
Author: 6C656C65
|
|
6
6
|
License-Expression: MIT
|
|
@@ -28,6 +28,7 @@ Requires-Dist: requests>=2.31.0
|
|
|
28
28
|
Requires-Dist: Flask>=3.1.0
|
|
29
29
|
Requires-Dist: Flask-HTTPAuth>=4.8.0
|
|
30
30
|
Requires-Dist: psutil>=5.9.8
|
|
31
|
+
Requires-Dist: colorlog>=6.9.0
|
|
31
32
|
Dynamic: license-file
|
|
32
33
|
|
|
33
34
|
<div align="center">
|
|
@@ -47,9 +48,8 @@ Dynamic: license-file
|
|
|
47
48
|
<img src="https://img.shields.io/github/commit-activity/w/6C656C65/pyproxy?style=for-the-badge">
|
|
48
49
|
<img src="https://img.shields.io/github/contributors/6C656C65/pyproxy?style=for-the-badge">
|
|
49
50
|
<br>
|
|
50
|
-
<img src="https://img.shields.io/
|
|
51
|
-
<img src="https://img.shields.io/
|
|
52
|
-
<img src="https://img.shields.io/github/actions/workflow/status/6C656C65/pyproxy/docker-images.yml?label=Delivery&style=for-the-badge">
|
|
51
|
+
<img src="https://img.shields.io/pypi/v/pyproxytools?style=for-the-badge">
|
|
52
|
+
<img src="https://img.shields.io/pypi/pyversions/pyproxytools?style=for-the-badge">
|
|
53
53
|
</p>
|
|
54
54
|
|
|
55
55
|
---
|
|
@@ -97,7 +97,7 @@ You can use slim images by adding `-slim` to the end of the tags
|
|
|
97
97
|
|
|
98
98
|
### Start the proxy
|
|
99
99
|
```bash
|
|
100
|
-
python3 -m pyproxy
|
|
100
|
+
python3 -m pyproxy
|
|
101
101
|
```
|
|
102
102
|
The proxy will be available at: `0.0.0.0:8080`.
|
|
103
103
|
The access log will be available at `./logs/access.log`.
|
|
@@ -15,9 +15,8 @@
|
|
|
15
15
|
<img src="https://img.shields.io/github/commit-activity/w/6C656C65/pyproxy?style=for-the-badge">
|
|
16
16
|
<img src="https://img.shields.io/github/contributors/6C656C65/pyproxy?style=for-the-badge">
|
|
17
17
|
<br>
|
|
18
|
-
<img src="https://img.shields.io/
|
|
19
|
-
<img src="https://img.shields.io/
|
|
20
|
-
<img src="https://img.shields.io/github/actions/workflow/status/6C656C65/pyproxy/docker-images.yml?label=Delivery&style=for-the-badge">
|
|
18
|
+
<img src="https://img.shields.io/pypi/v/pyproxytools?style=for-the-badge">
|
|
19
|
+
<img src="https://img.shields.io/pypi/pyversions/pyproxytools?style=for-the-badge">
|
|
21
20
|
</p>
|
|
22
21
|
|
|
23
22
|
---
|
|
@@ -65,7 +64,7 @@ You can use slim images by adding `-slim` to the end of the tags
|
|
|
65
64
|
|
|
66
65
|
### Start the proxy
|
|
67
66
|
```bash
|
|
68
|
-
python3 -m pyproxy
|
|
67
|
+
python3 -m pyproxy
|
|
69
68
|
```
|
|
70
69
|
The proxy will be available at: `0.0.0.0:8080`.
|
|
71
70
|
The access log will be available at `./logs/access.log`.
|
|
@@ -39,9 +39,7 @@ class ProxyHandlers:
|
|
|
39
39
|
shortcuts,
|
|
40
40
|
custom_header,
|
|
41
41
|
active_connections,
|
|
42
|
-
|
|
43
|
-
proxy_host,
|
|
44
|
-
proxy_port,
|
|
42
|
+
proxy_config,
|
|
45
43
|
):
|
|
46
44
|
self.html_403 = html_403
|
|
47
45
|
self.logger_config = logger_config
|
|
@@ -58,11 +56,32 @@ class ProxyHandlers:
|
|
|
58
56
|
self.console_logger = console_logger
|
|
59
57
|
self.config_shortcuts = shortcuts
|
|
60
58
|
self.config_custom_header = custom_header
|
|
61
|
-
self.
|
|
62
|
-
self.proxy_host = proxy_host
|
|
63
|
-
self.proxy_port = proxy_port
|
|
59
|
+
self.proxy_config = proxy_config
|
|
64
60
|
self.active_connections = active_connections
|
|
65
61
|
|
|
62
|
+
def _create_handler(self, handler_class, **extra_kwargs):
|
|
63
|
+
"""
|
|
64
|
+
Factory to create handler instance with shared common parameters.
|
|
65
|
+
"""
|
|
66
|
+
params = dict(
|
|
67
|
+
html_403=self.html_403,
|
|
68
|
+
logger_config=self.logger_config,
|
|
69
|
+
filter_config=self.filter_config,
|
|
70
|
+
filter_queue=self.filter_queue,
|
|
71
|
+
filter_result_queue=self.filter_result_queue,
|
|
72
|
+
shortcuts_queue=self.shortcuts_queue,
|
|
73
|
+
shortcuts_result_queue=self.shortcuts_result_queue,
|
|
74
|
+
custom_header_queue=self.custom_header_queue,
|
|
75
|
+
custom_header_result_queue=self.custom_header_result_queue,
|
|
76
|
+
console_logger=self.console_logger,
|
|
77
|
+
shortcuts=self.config_shortcuts,
|
|
78
|
+
custom_header=self.config_custom_header,
|
|
79
|
+
proxy_config=self.proxy_config,
|
|
80
|
+
active_connections=self.active_connections,
|
|
81
|
+
)
|
|
82
|
+
params.update(extra_kwargs)
|
|
83
|
+
return handler_class(**params)
|
|
84
|
+
|
|
66
85
|
def handle_client(self, client_socket):
|
|
67
86
|
"""
|
|
68
87
|
Handles an incoming client connection by processing the request and forwarding
|
|
@@ -82,45 +101,13 @@ class ProxyHandlers:
|
|
|
82
101
|
first_line = request.decode(errors="ignore").split("\n")[0]
|
|
83
102
|
|
|
84
103
|
if first_line.startswith("CONNECT"):
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
logger_config=self.logger_config,
|
|
88
|
-
filter_config=self.filter_config,
|
|
104
|
+
https_handler = self._create_handler(
|
|
105
|
+
HttpsHandler,
|
|
89
106
|
ssl_config=self.ssl_config,
|
|
90
|
-
filter_queue=self.filter_queue,
|
|
91
|
-
filter_result_queue=self.filter_result_queue,
|
|
92
|
-
shortcuts_queue=self.shortcuts_queue,
|
|
93
|
-
shortcuts_result_queue=self.shortcuts_result_queue,
|
|
94
107
|
cancel_inspect_queue=self.cancel_inspect_queue,
|
|
95
108
|
cancel_inspect_result_queue=self.cancel_inspect_result_queue,
|
|
96
|
-
custom_header_queue=self.custom_header_queue,
|
|
97
|
-
custom_header_result_queue=self.custom_header_result_queue,
|
|
98
|
-
console_logger=self.console_logger,
|
|
99
|
-
shortcuts=self.config_shortcuts,
|
|
100
|
-
custom_header=self.config_custom_header,
|
|
101
|
-
proxy_enable=self.proxy_enable,
|
|
102
|
-
proxy_host=self.proxy_host,
|
|
103
|
-
proxy_port=self.proxy_port,
|
|
104
|
-
active_connections=self.active_connections,
|
|
105
109
|
)
|
|
106
|
-
|
|
110
|
+
https_handler.handle_https_connection(client_socket, first_line)
|
|
107
111
|
else:
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
logger_config=self.logger_config,
|
|
111
|
-
filter_config=self.filter_config,
|
|
112
|
-
filter_queue=self.filter_queue,
|
|
113
|
-
filter_result_queue=self.filter_result_queue,
|
|
114
|
-
shortcuts_queue=self.shortcuts_queue,
|
|
115
|
-
shortcuts_result_queue=self.shortcuts_result_queue,
|
|
116
|
-
custom_header_queue=self.custom_header_queue,
|
|
117
|
-
custom_header_result_queue=self.custom_header_result_queue,
|
|
118
|
-
console_logger=self.console_logger,
|
|
119
|
-
shortcuts=self.config_shortcuts,
|
|
120
|
-
custom_header=self.config_custom_header,
|
|
121
|
-
proxy_enable=self.proxy_enable,
|
|
122
|
-
proxy_host=self.proxy_host,
|
|
123
|
-
proxy_port=self.proxy_port,
|
|
124
|
-
active_connections=self.active_connections,
|
|
125
|
-
)
|
|
126
|
-
client_http_handler.handle_http_request(client_socket, request)
|
|
112
|
+
http_handler = self._create_handler(HttpHandler)
|
|
113
|
+
http_handler.handle_http_request(client_socket, request)
|
|
@@ -8,8 +8,9 @@ HTTP client connections. It handles request forwarding, blocking, and custom hea
|
|
|
8
8
|
import socket
|
|
9
9
|
import os
|
|
10
10
|
import threading
|
|
11
|
+
from urllib.parse import urlparse
|
|
11
12
|
|
|
12
|
-
from pyproxy.utils.http_req import extract_headers
|
|
13
|
+
from pyproxy.utils.http_req import extract_headers
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
class HttpHandler:
|
|
@@ -34,9 +35,7 @@ class HttpHandler:
|
|
|
34
35
|
shortcuts,
|
|
35
36
|
custom_header,
|
|
36
37
|
active_connections,
|
|
37
|
-
|
|
38
|
-
proxy_host,
|
|
39
|
-
proxy_port,
|
|
38
|
+
proxy_config,
|
|
40
39
|
):
|
|
41
40
|
self.html_403 = html_403
|
|
42
41
|
self.logger_config = logger_config
|
|
@@ -50,11 +49,81 @@ class HttpHandler:
|
|
|
50
49
|
self.console_logger = console_logger
|
|
51
50
|
self.config_shortcuts = shortcuts
|
|
52
51
|
self.config_custom_header = custom_header
|
|
53
|
-
self.
|
|
54
|
-
self.proxy_host = proxy_host
|
|
55
|
-
self.proxy_port = proxy_port
|
|
52
|
+
self.proxy_config = proxy_config
|
|
56
53
|
self.active_connections = active_connections
|
|
57
54
|
|
|
55
|
+
def _get_modified_headers(self, url, request_text):
|
|
56
|
+
"""
|
|
57
|
+
Extract headers from a request
|
|
58
|
+
"""
|
|
59
|
+
headers = extract_headers(request_text)
|
|
60
|
+
self.custom_header_queue.put(url)
|
|
61
|
+
try:
|
|
62
|
+
new_headers = self.custom_header_result_queue.get(timeout=5)
|
|
63
|
+
headers.update(new_headers)
|
|
64
|
+
except Exception:
|
|
65
|
+
self.console_logger.warning(
|
|
66
|
+
"Timeout while getting custom headers for %s", url
|
|
67
|
+
)
|
|
68
|
+
return headers
|
|
69
|
+
|
|
70
|
+
def _rebuild_http_request(self, request_line, headers, body=""):
|
|
71
|
+
"""
|
|
72
|
+
Reconstructs an HTTP request with the new headers.
|
|
73
|
+
"""
|
|
74
|
+
header_lines = [f"{key}: {value}" for key, value in headers.items()]
|
|
75
|
+
reconstructed_headers = "\r\n".join(header_lines)
|
|
76
|
+
return f"{request_line}\r\n{reconstructed_headers}\r\n\r\n{body}".encode()
|
|
77
|
+
|
|
78
|
+
def _apply_shortcut(self, url: str) -> str | None:
|
|
79
|
+
"""
|
|
80
|
+
Checks if a shortcut is defined for the given domain.
|
|
81
|
+
"""
|
|
82
|
+
if self.config_shortcuts and os.path.isfile(self.config_shortcuts):
|
|
83
|
+
parsed_url = urlparse(url)
|
|
84
|
+
domain = parsed_url.hostname
|
|
85
|
+
self.shortcuts_queue.put(domain)
|
|
86
|
+
try:
|
|
87
|
+
return self.shortcuts_result_queue.get(timeout=5)
|
|
88
|
+
except Exception:
|
|
89
|
+
self.console_logger.warning(
|
|
90
|
+
"Timeout while getting shortcut for %s", url
|
|
91
|
+
)
|
|
92
|
+
return None
|
|
93
|
+
|
|
94
|
+
def _is_blocked(self, url: str) -> bool:
|
|
95
|
+
"""
|
|
96
|
+
Checks if a URL is blocked by the configuration filter.
|
|
97
|
+
"""
|
|
98
|
+
if not self.filter_config.no_filter:
|
|
99
|
+
self.filter_queue.put(url)
|
|
100
|
+
try:
|
|
101
|
+
result = self.filter_result_queue.get(timeout=5)
|
|
102
|
+
return result[1] == "Blocked"
|
|
103
|
+
except Exception:
|
|
104
|
+
self.console_logger.warning("Timeout while filtering %s", url)
|
|
105
|
+
return False
|
|
106
|
+
|
|
107
|
+
def _send_403(self, client_socket, url, first_line):
|
|
108
|
+
"""
|
|
109
|
+
Sends an HTTP 403 Forbidden response to the client.
|
|
110
|
+
"""
|
|
111
|
+
if not self.logger_config.no_logging_block:
|
|
112
|
+
self.logger_config.block_logger.info(
|
|
113
|
+
"%s - %s - %s", client_socket.getpeername()[0], url, first_line
|
|
114
|
+
)
|
|
115
|
+
with open(self.html_403, "r", encoding="utf-8") as f:
|
|
116
|
+
custom_403_page = f.read()
|
|
117
|
+
response = (
|
|
118
|
+
f"HTTP/1.1 403 Forbidden\r\n"
|
|
119
|
+
f"Content-Length: {len(custom_403_page)}\r\n"
|
|
120
|
+
f"\r\n"
|
|
121
|
+
f"{custom_403_page}"
|
|
122
|
+
)
|
|
123
|
+
client_socket.sendall(response.encode())
|
|
124
|
+
client_socket.close()
|
|
125
|
+
self.active_connections.pop(threading.get_ident(), None)
|
|
126
|
+
|
|
58
127
|
def handle_http_request(self, client_socket, request):
|
|
59
128
|
"""
|
|
60
129
|
Processes an HTTP request, checks for URL filtering, applies shortcuts,
|
|
@@ -67,16 +136,8 @@ class HttpHandler:
|
|
|
67
136
|
first_line = request.decode(errors="ignore").split("\n")[0]
|
|
68
137
|
url = first_line.split(" ")[1]
|
|
69
138
|
|
|
70
|
-
if self.config_custom_header and os.path.isfile(self.config_custom_header):
|
|
71
|
-
headers = extract_headers(request.decode(errors="ignore"))
|
|
72
|
-
self.custom_header_queue.put(url)
|
|
73
|
-
new_headers = self.custom_header_result_queue.get(timeout=5)
|
|
74
|
-
headers.update(new_headers)
|
|
75
|
-
|
|
76
139
|
if self.config_shortcuts and os.path.isfile(self.config_shortcuts):
|
|
77
|
-
|
|
78
|
-
self.shortcuts_queue.put(domain)
|
|
79
|
-
shortcut_url = self.shortcuts_result_queue.get(timeout=5)
|
|
140
|
+
shortcut_url = self._apply_shortcut(url)
|
|
80
141
|
if shortcut_url:
|
|
81
142
|
response = (
|
|
82
143
|
f"HTTP/1.1 302 Found\r\n"
|
|
@@ -90,27 +151,12 @@ class HttpHandler:
|
|
|
90
151
|
self.active_connections.pop(threading.get_ident(), None)
|
|
91
152
|
return
|
|
92
153
|
|
|
93
|
-
if
|
|
94
|
-
self.
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
"%s - %s - %s", client_socket.getpeername()[0], url, first_line
|
|
100
|
-
)
|
|
101
|
-
with open(self.html_403, "r", encoding="utf-8") as f:
|
|
102
|
-
custom_403_page = f.read()
|
|
103
|
-
response = (
|
|
104
|
-
f"HTTP/1.1 403 Forbidden\r\n"
|
|
105
|
-
f"Content-Length: {len(custom_403_page)}\r\n"
|
|
106
|
-
f"\r\n"
|
|
107
|
-
f"{custom_403_page}"
|
|
108
|
-
)
|
|
109
|
-
client_socket.sendall(response.encode())
|
|
110
|
-
client_socket.close()
|
|
111
|
-
self.active_connections.pop(threading.get_ident(), None)
|
|
112
|
-
return
|
|
113
|
-
server_host, _ = parse_url(url)
|
|
154
|
+
if self._is_blocked(url):
|
|
155
|
+
self._send_403(client_socket, url, first_line)
|
|
156
|
+
return
|
|
157
|
+
|
|
158
|
+
parsed_url = urlparse(url)
|
|
159
|
+
server_host = parsed_url.hostname
|
|
114
160
|
if not self.logger_config.no_logging_access:
|
|
115
161
|
self.logger_config.access_logger.info(
|
|
116
162
|
"%s - %s - %s",
|
|
@@ -120,20 +166,16 @@ class HttpHandler:
|
|
|
120
166
|
)
|
|
121
167
|
|
|
122
168
|
if self.config_custom_header and os.path.isfile(self.config_custom_header):
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
else:
|
|
132
|
-
body = ""
|
|
133
|
-
|
|
134
|
-
modified_request = (
|
|
135
|
-
f"{request_line}\r\n{reconstructed_headers}\r\n\r\n{body}".encode()
|
|
169
|
+
request_text = request.decode(errors="ignore")
|
|
170
|
+
request_lines = request_text.split("\r\n")
|
|
171
|
+
headers = self._get_modified_headers(url, request_text)
|
|
172
|
+
request_line = request_lines[0]
|
|
173
|
+
body = (
|
|
174
|
+
request_text.split("\r\n\r\n", 1)[1]
|
|
175
|
+
if "\r\n\r\n" in request_text
|
|
176
|
+
else ""
|
|
136
177
|
)
|
|
178
|
+
modified_request = self._rebuild_http_request(request_line, headers, body)
|
|
137
179
|
|
|
138
180
|
self.forward_request_to_server(client_socket, modified_request, url)
|
|
139
181
|
|
|
@@ -149,10 +191,14 @@ class HttpHandler:
|
|
|
149
191
|
request (bytes): The raw HTTP request sent by the client.
|
|
150
192
|
url (str): The target URL from the HTTP request.
|
|
151
193
|
"""
|
|
152
|
-
if self.
|
|
153
|
-
server_host, server_port = self.
|
|
194
|
+
if self.proxy_config.enable:
|
|
195
|
+
server_host, server_port = self.proxy_config.host, self.proxy_config.port
|
|
154
196
|
else:
|
|
155
|
-
|
|
197
|
+
parsed_url = urlparse(url)
|
|
198
|
+
server_host = parsed_url.hostname
|
|
199
|
+
server_port = parsed_url.port or (
|
|
200
|
+
443 if parsed_url.scheme == "https" else 80
|
|
201
|
+
)
|
|
156
202
|
thread_id = threading.get_ident()
|
|
157
203
|
|
|
158
204
|
if thread_id in self.active_connections:
|