Mythus commited on
Commit
87b4a88
·
verified ·
1 Parent(s): 57a0f0e

Update run.py

Browse files
Files changed (1) hide show
  1. run.py +35 -65
run.py CHANGED
@@ -1,78 +1,48 @@
1
- import socket
2
- import asyncio
3
- from contextlib import asynccontextmanager
4
- from typing import AsyncIterator
5
-
6
- from fastapi import FastAPI, Request, Response
7
  from fastapi_proxy_lib.core.http import ForwardHttpProxy
8
  from fastapi_proxy_lib.core.tool import default_proxy_filter
9
  from httpx import AsyncClient
 
10
 
11
  proxy = ForwardHttpProxy(AsyncClient(), proxy_filter=default_proxy_filter)
12
 
13
- @asynccontextmanager
14
- async def close_proxy_event(_: FastAPI) -> AsyncIterator[None]:
15
- """Close proxy."""
16
- yield
17
- await proxy.aclose()
18
-
19
- app = FastAPI(lifespan=close_proxy_event)
20
 
21
- # Handle all regular HTTP methods via the proxy
22
  @app.api_route("/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"])
23
- async def proxy_request(request: Request, path: str = ""):
24
- """Handle HTTP requests."""
25
- return await proxy.proxy(request=request, path=path)
26
-
27
- # Manually handle the CONNECT method for HTTPS tunneling
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  @app.api_route("/{path:path}", methods=["CONNECT"])
29
  async def handle_connect(request: Request):
30
- """Handle the CONNECT method for HTTPS tunneling."""
31
- client_host = request.url.hostname
32
- client_port = request.url.port or 443 # Use default HTTPS port if not specified
33
-
34
- # Establish a connection to the target server
35
- client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
36
- client_socket.settimeout(10)
37
- client_socket.connect((client_host, client_port))
38
-
39
- # Send back a 200 Connection Established response to the client
40
- writer = request.scope["client"]
41
- await writer.write(b"HTTP/1.1 200 Connection Established\r\n\r\n")
42
- await writer.drain()
43
-
44
- # Setup forwarding between the client and the target server
45
- loop = asyncio.get_event_loop()
46
-
47
- async def forward_data(reader, sock):
48
- try:
49
- while True:
50
- data = await reader.read(1024)
51
- if not data:
52
- break
53
- sock.sendall(data)
54
- finally:
55
- sock.close()
56
-
57
- async def reverse_data(sock, writer):
58
- try:
59
- while True:
60
- data = sock.recv(1024)
61
- if not data:
62
- break
63
- await writer.write(data)
64
- await writer.drain()
65
- finally:
66
- writer.close()
67
-
68
- # Create bidirectional data forwarding
69
- client_reader, client_writer = await asyncio.open_connection(sock=client_socket)
70
- forward_task = loop.create_task(forward_data(client_reader, client_socket))
71
- reverse_task = loop.create_task(reverse_data(client_socket, client_writer))
72
-
73
- await asyncio.gather(forward_task, reverse_task)
74
- return Response(status_code=200)
75
 
76
  if __name__ == '__main__':
77
  import uvicorn
78
- uvicorn.run("run:app", host="0.0.0.0", port=8080)
 
1
+ from fastapi import FastAPI, Request
2
+ from fastapi.responses import Response
 
 
 
 
3
  from fastapi_proxy_lib.core.http import ForwardHttpProxy
4
  from fastapi_proxy_lib.core.tool import default_proxy_filter
5
  from httpx import AsyncClient
6
+ import re
7
 
8
  proxy = ForwardHttpProxy(AsyncClient(), proxy_filter=default_proxy_filter)
9
 
10
+ app = FastAPI()
 
 
 
 
 
 
11
 
12
+ # Handle HTTP(S) requests through the proxy
13
  @app.api_route("/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"])
14
+ async def handle_proxy(request: Request, path: str = ""):
15
+ """
16
+ Handles HTTP requests and forwards them to the destination URL.
17
+ """
18
+ # Extract the destination URL from the request headers
19
+ target_url = request.headers.get("host", "")
20
+
21
+ if target_url:
22
+ scheme = "https" if request.url.port == 443 else "http"
23
+ # Reconstruct the full URL
24
+ forward_url = f"{scheme}://{target_url}{request.url.path}"
25
+
26
+ # Forward the request to the actual destination using ForwardHttpProxy
27
+ return await proxy.proxy(request=request, path=forward_url)
28
+ return Response(content="Host header not found", status_code=400)
29
+
30
+
31
+ # Handle HTTPS requests with CONNECT method (to establish a tunnel)
32
  @app.api_route("/{path:path}", methods=["CONNECT"])
33
  async def handle_connect(request: Request):
34
+ """
35
+ Handles CONNECT method for HTTPS proxying.
36
+ This is for forwarding HTTPS requests via curl -x.
37
+ """
38
+ # Extract the target host and port from the request's URL
39
+ match = re.match(r"^([^:]+):(\d+)$", request.url.path)
40
+ if match:
41
+ host, port = match.groups()
42
+ return await proxy.proxy(request=request, path=f"https://{host}:{port}")
43
+
44
+ return Response(content="Invalid CONNECT request", status_code=400)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
  if __name__ == '__main__':
47
  import uvicorn
48
+ uvicorn.run("run:app", host="0.0.0.0", port=8080)