You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
3.5 KiB
113 lines
3.5 KiB
from flask import Flask, request, Response
|
|
import requests
|
|
import re
|
|
|
|
app = Flask(__name__)
|
|
|
|
# 首页
|
|
@app.route('/')
|
|
def home():
|
|
return '''
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>🌐 国外网站代理访问</title>
|
|
<style>
|
|
body { font-family: sans-serif; background: #f9f9f9; text-align: center; padding-top: 120px; }
|
|
h1 { font-size: 42px; margin-bottom: 40px; color: #333; }
|
|
form { margin: 0 auto; width: 450px; }
|
|
input[type="text"] {
|
|
width: 300px; padding: 12px;
|
|
font-size: 18px;
|
|
border: 1px solid #ccc;
|
|
border-radius: 6px;
|
|
}
|
|
button {
|
|
padding: 12px 24px;
|
|
font-size: 18px;
|
|
background: #4285F4;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
margin-left: 10px;
|
|
}
|
|
button:hover { background: #3367d6; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>🌐 Github / 国外网站加速代理</h1>
|
|
<form action="/proxy" method="get">
|
|
<input type="text" name="url" placeholder="例如 github.com 或 https://google.com">
|
|
<button type="submit">🚀 访问</button>
|
|
</form>
|
|
</body>
|
|
</html>
|
|
'''
|
|
|
|
# 统一替换 html 内资源链接与表单 action
|
|
def replace_all_resources(html, target_url):
|
|
def replace_match(match):
|
|
attr, url = match.group(1), match.group(2)
|
|
if url.startswith('http'):
|
|
proxied_url = f"/proxy?url={url}"
|
|
elif url.startswith('//'):
|
|
proxied_url = f"/proxy?url=https:{url}"
|
|
elif url.startswith('/'):
|
|
base = re.match(r'(https?://[^/]+)', target_url).group(1)
|
|
proxied_url = f"/proxy?url={base}{url}"
|
|
else:
|
|
base = target_url.rsplit('/', 1)[0]
|
|
proxied_url = f"/proxy?url={base}/{url}"
|
|
return f'{attr}="{proxied_url}"'
|
|
|
|
# 替换 src / href / action
|
|
html = re.sub(r'(src|href|action)=["\'](.*?)["\']', replace_match, html, flags=re.IGNORECASE)
|
|
|
|
# 给所有表单加隐藏 input 保留 url 参数
|
|
html = re.sub(
|
|
r'(<form[^>]*>)',
|
|
lambda m: f'{m.group(1)}<input type="hidden" name="url" value="{target_url}">',
|
|
html,
|
|
flags=re.IGNORECASE
|
|
)
|
|
|
|
return html
|
|
|
|
# 代理接口
|
|
@app.route('/proxy')
|
|
def proxy():
|
|
target_url = request.args.get('url')
|
|
if not target_url:
|
|
return '❌ 缺少 url 参数'
|
|
|
|
# 自动补全 https://
|
|
if not target_url.startswith(('http://', 'https://')):
|
|
target_url = 'https://' + target_url
|
|
|
|
try:
|
|
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'}
|
|
resp = requests.get(target_url, headers=headers, timeout=8)
|
|
|
|
content_type = resp.headers.get('Content-Type', '')
|
|
|
|
# 如果是 HTML 页面
|
|
if 'text/html' in content_type:
|
|
html = resp.text
|
|
# 替换资源和表单 action
|
|
html = replace_all_resources(html, target_url)
|
|
return Response(html, resp.status_code, content_type=content_type)
|
|
|
|
else:
|
|
# 其他类型直接转发
|
|
return Response(resp.content, resp.status_code, content_type=content_type)
|
|
|
|
except requests.exceptions.RequestException as e:
|
|
return f'❌ 网络异常: {e}'
|
|
except Exception as e:
|
|
return f'❌ 系统错误: {e}'
|
|
|
|
# 启动服务
|
|
if __name__ == '__main__':
|
|
app.run(host='0.0.0.0', port=8203)
|