aigenai commited on
Commit
055b4d1
·
verified ·
1 Parent(s): e510d55

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +89 -11
app.py CHANGED
@@ -31,37 +31,50 @@ class Config:
31
  """配置类"""
32
  ASSET_URL = "https://1pages.nbid.bid/"
33
  PREFIX = "/"
34
- JSDELIVR = 0
35
  CACHE_TTL = 3600
36
  MAX_RETRIES = 3
37
  TIMEOUT = 10
 
 
 
38
  RATE_LIMIT = {
39
  "window_ms": 15 * 60 * 1000, # 15分钟
40
  "max": 100 # 限制每个IP最多100个请求
41
  }
42
  WHITE_LIST: List[str] = [] # 白名单
 
 
43
 
44
  # 请求头
45
  DEFAULT_HEADERS = {
46
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
 
 
47
  }
48
 
49
  # CORS设置
50
  CORS = {
51
  "allow_origins": ["*"],
52
- "allow_methods": ["GET", "POST", "OPTIONS"],
53
  "allow_headers": ["*"],
54
  "max_age": 1728000
55
  }
56
 
57
- # URL模式
58
  PATTERNS = {
59
- "releases": r"^(?:https?:\/\/)?github\.com\/.+?\/.+?\/(?:releases|archive)\/.*$",
60
- "blob": r"^(?:https?:\/\/)?github\.com\/.+?\/.+?\/(?:blob|raw)\/.*$",
61
- "git": r"^(?:https?:\/\/)?github\.com\/.+?\/.+?\/(?:info|git-).*$",
62
- "raw": r"^(?:https?:\/\/)?raw\.(?:githubusercontent|github)\.com\/.+?\/.+?\/.+?\/.+$",
63
- "gist": r"^(?:https?:\/\/)?gist\.(?:githubusercontent|github)\.com\/.+?\/.+?\/.+$",
64
- "tags": r"^(?:https?:\/\/)?github\.com\/.+?\/.+?\/tags.*$"
 
 
 
 
 
 
65
  }
66
 
67
  class RateLimiter:
@@ -263,6 +276,58 @@ def create_interface():
263
  path = 'https://' + path
264
 
265
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
266
  # 获取代理响应
267
  response = proxy.proxy_request(path, request)
268
 
@@ -277,10 +342,23 @@ def create_interface():
277
  if proxy_response.error:
278
  return JSONResponse({"error": proxy_response.error}, status_code=proxy_response.status)
279
 
 
 
 
 
 
280
  # 返回流式响应
281
  headers = dict(proxy_response.headers)
 
 
 
 
 
 
 
 
282
  return StreamingResponse(
283
- proxy_response.content.iter_content(chunk_size=8192),
284
  headers=headers,
285
  status_code=proxy_response.status
286
  )
 
31
  """配置类"""
32
  ASSET_URL = "https://1pages.nbid.bid/"
33
  PREFIX = "/"
34
+ JSDELIVR = 0 # 是否使用 jsDelivr 镜像
35
  CACHE_TTL = 3600
36
  MAX_RETRIES = 3
37
  TIMEOUT = 10
38
+ CHUNK_SIZE = 1024 * 10 # 10KB 分块大小
39
+ SIZE_LIMIT = 1024 * 1024 * 1024 * 999 # 999GB 文件大小限制
40
+
41
  RATE_LIMIT = {
42
  "window_ms": 15 * 60 * 1000, # 15分钟
43
  "max": 100 # 限制每个IP最多100个请求
44
  }
45
  WHITE_LIST: List[str] = [] # 白名单
46
+ BLACK_LIST: List[str] = [] # 黑名单
47
+ PASS_LIST: List[str] = [] # 直接通过名单(使用 jsDelivr)
48
 
49
  # 请求头
50
  DEFAULT_HEADERS = {
51
+ "User-Agent": "git/2.41.0", # 使用 Git 用户代理
52
+ "Accept": "*/*",
53
+ "Accept-Encoding": "gzip, deflate, br"
54
  }
55
 
56
  # CORS设置
57
  CORS = {
58
  "allow_origins": ["*"],
59
+ "allow_methods": ["GET", "POST", "OPTIONS", "HEAD"],
60
  "allow_headers": ["*"],
61
  "max_age": 1728000
62
  }
63
 
64
+ # URL模式(完善匹配模式)
65
  PATTERNS = {
66
+ # 发布和归档
67
+ "releases": r"^(?:https?:\/\/)?github\.com\/(?P<author>.+?)\/(?P<repo>.+?)\/(?:releases|archive)\/.*$",
68
+ # blob和raw文件
69
+ "blob": r"^(?:https?:\/\/)?github\.com\/(?P<author>.+?)\/(?P<repo>.+?)\/(?:blob|raw)\/.*$",
70
+ # Git操作
71
+ "git": r"^(?:https?:\/\/)?github\.com\/(?P<author>.+?)\/(?P<repo>.+?)\/(?:info\/refs\?service=)?git-.*$",
72
+ # Raw内容
73
+ "raw": r"^(?:https?:\/\/)?raw\.(?:githubusercontent|github)\.com\/(?P<author>.+?)\/(?P<repo>.+?)\/.+?\/.+$",
74
+ # Gist
75
+ "gist": r"^(?:https?:\/\/)?gist\.(?:githubusercontent|github)\.com\/(?P<author>.+?)\/.+?\/.+$",
76
+ # 标签
77
+ "tags": r"^(?:https?:\/\/)?github\.com\/(?P<author>.+?)\/(?P<repo>.+?)\/tags.*$"
78
  }
79
 
80
  class RateLimiter:
 
276
  path = 'https://' + path
277
 
278
  try:
279
+ # 检查URL格式
280
+ match = None
281
+ for pattern in Config.PATTERNS.values():
282
+ if re.match(pattern, path):
283
+ match = re.match(pattern, path)
284
+ break
285
+
286
+ if not match:
287
+ return JSONResponse({"error": "不支持的URL格式"}, status_code=400)
288
+
289
+ # 检查白名单和黑名单
290
+ author, repo = match.group('author', 'repo')
291
+ if Config.WHITE_LIST and not any(
292
+ (a == '*' or a == author) and (r == '*' or r == repo)
293
+ for a, r in [x.split('/') for x in Config.WHITE_LIST]
294
+ ):
295
+ return JSONResponse({"error": "不在白名单中"}, status_code=403)
296
+
297
+ if any(
298
+ (a == '*' or a == author) and (r == '*' or r == repo)
299
+ for a, r in [x.split('/') for x in Config.BLACK_LIST]
300
+ ):
301
+ return JSONResponse({"error": "在黑名单中"}, status_code=403)
302
+
303
+ # 处理 jsDelivr 重定向
304
+ use_jsdelivr = Config.JSDELIVR or any(
305
+ (a == '*' or a == author) and (r == '*' or r == repo)
306
+ for a, r in [x.split('/') for x in Config.PASS_LIST]
307
+ )
308
+
309
+ if use_jsdelivr and ('blob' in path or 'raw.githubusercontent.com' in path):
310
+ # 转换为 jsDelivr URL
311
+ if 'blob' in path:
312
+ path = path.replace('/blob/', '@').replace('github.com', 'cdn.jsdelivr.net/gh', 1)
313
+ else:
314
+ path = re.sub(r'(\.com/.*?/.+?)/(.+?/)', r'\1@\2', path, 1)
315
+ path = path.replace('raw.githubusercontent.com', 'cdn.jsdelivr.net/gh', 1)
316
+ return RedirectResponse(path)
317
+
318
+ # 处理 blob 到 raw 的转换
319
+ if 'blob' in path:
320
+ path = path.replace('/blob/', '/raw/', 1)
321
+
322
+ # 处理 Git 请求
323
+ if 'git-upload-pack' in path or 'git-receive-pack' in path or 'info/refs' in path:
324
+ headers = dict(request.headers)
325
+ headers.update({
326
+ 'User-Agent': 'git/2.41.0',
327
+ 'Accept': 'application/x-git-upload-pack-result, */*',
328
+ })
329
+ proxy.session.headers.update(headers)
330
+
331
  # 获取代理响应
332
  response = proxy.proxy_request(path, request)
333
 
 
342
  if proxy_response.error:
343
  return JSONResponse({"error": proxy_response.error}, status_code=proxy_response.status)
344
 
345
+ # 检查文件大小限制
346
+ content_length = int(proxy_response.headers.get('content-length', 0))
347
+ if content_length > Config.SIZE_LIMIT:
348
+ return RedirectResponse(path)
349
+
350
  # 返回流式响应
351
  headers = dict(proxy_response.headers)
352
+ # 设置正确的内容类型
353
+ if 'git-upload-pack' in path:
354
+ headers['Content-Type'] = 'application/x-git-upload-pack-result'
355
+ elif 'git-receive-pack' in path:
356
+ headers['Content-Type'] = 'application/x-git-receive-pack-result'
357
+ elif 'info/refs' in path:
358
+ headers['Content-Type'] = 'application/x-git-upload-pack-advertisement'
359
+
360
  return StreamingResponse(
361
+ proxy_response.content.iter_content(chunk_size=Config.CHUNK_SIZE),
362
  headers=headers,
363
  status_code=proxy_response.status
364
  )