Files
taiji-AI-PAD/scripts/https_proxy.py
2026-03-15 15:30:24 +00:00

148 lines
4.7 KiB
Python

#!/usr/bin/env python3
"""
HTTPS 代理服务器
用于测试环境,将 HTTPS 请求转发到本地 HTTP 服务
使用方法:
python3 https_proxy.py --port 8989 --target http://localhost:8000 \
--cert ssl_certs/cert.pem --key ssl_certs/key.pem
"""
import argparse
import ssl
import http.server
import urllib.request
import urllib.error
import socketserver
import json
from urllib.parse import urlparse
class ProxyHandler(http.server.BaseHTTPRequestHandler):
"""HTTPS 到 HTTP 代理处理器"""
target_url = "http://localhost:8000"
def do_request(self, method: str):
"""处理所有 HTTP 方法"""
# 构建目标 URL
target = f"{self.target_url}{self.path}"
# 读取请求体
content_length = int(self.headers.get('Content-Length', 0))
body = self.rfile.read(content_length) if content_length > 0 else None
# 构建请求头(转发原始头)
headers = {}
for key, value in self.headers.items():
# 跳过 hop-by-hop 头
if key.lower() not in ('host', 'connection', 'keep-alive',
'transfer-encoding', 'te', 'trailer',
'proxy-authorization', 'proxy-authenticate',
'upgrade'):
headers[key] = value
# 添加 X-Forwarded 头
headers['X-Forwarded-For'] = self.client_address[0]
headers['X-Forwarded-Proto'] = 'https'
try:
# 创建请求
req = urllib.request.Request(
target,
data=body,
headers=headers,
method=method
)
# 发送请求
with urllib.request.urlopen(req, timeout=30) as response:
# 发送响应状态
self.send_response(response.status)
# 转发响应头
for key, value in response.headers.items():
if key.lower() not in ('transfer-encoding', 'connection'):
self.send_header(key, value)
self.end_headers()
# 转发响应体
self.wfile.write(response.read())
except urllib.error.HTTPError as e:
self.send_response(e.code)
for key, value in e.headers.items():
if key.lower() not in ('transfer-encoding', 'connection'):
self.send_header(key, value)
self.end_headers()
self.wfile.write(e.read())
except urllib.error.URLError as e:
self.send_error(502, f"Bad Gateway: {e.reason}")
except Exception as e:
self.send_error(500, f"Internal Server Error: {str(e)}")
def do_GET(self):
self.do_request('GET')
def do_POST(self):
self.do_request('POST')
def do_PUT(self):
self.do_request('PUT')
def do_DELETE(self):
self.do_request('DELETE')
def do_PATCH(self):
self.do_request('PATCH')
def do_OPTIONS(self):
self.do_request('OPTIONS')
def log_message(self, format, *args):
"""自定义日志格式"""
print(f"[HTTPS Proxy] {self.client_address[0]} - {format % args}")
class ThreadedHTTPServer(socketserver.ThreadingMixIn, http.server.HTTPServer):
"""支持多线程的 HTTP 服务器"""
daemon_threads = True
def main():
parser = argparse.ArgumentParser(description='HTTPS to HTTP Proxy Server')
parser.add_argument('--port', type=int, default=8989, help='HTTPS port to listen on')
parser.add_argument('--target', default='http://localhost:8000', help='Target HTTP URL')
parser.add_argument('--cert', required=True, help='SSL certificate file')
parser.add_argument('--key', required=True, help='SSL private key file')
args = parser.parse_args()
# 设置目标 URL
ProxyHandler.target_url = args.target.rstrip('/')
# 创建 SSL 上下文
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ssl_context.load_cert_chain(args.cert, args.key)
# 创建服务器
server = ThreadedHTTPServer(('0.0.0.0', args.port), ProxyHandler)
server.socket = ssl_context.wrap_socket(server.socket, server_side=True)
print(f"HTTPS Proxy Server started on port {args.port}")
print(f"Forwarding to: {args.target}")
print(f"Press Ctrl+C to stop")
print()
try:
server.serve_forever()
except KeyboardInterrupt:
print("\nShutting down...")
server.shutdown()
if __name__ == '__main__':
main()