Use python to proxy http by sanic

Code:

#!/usr/bin/env python
import re
 
# pip install httpx orjson loguru sanic gunicorn 'uvicorn[standard]'
from httpx import AsyncClient
from loguru import logger
from orjson import dumps, loads
from sanic import Sanic, raw
 
app = Sanic("Jumper", dumps=dumps, loads=loads)
 
 
@app.route("", methods=["GET", "POST", "PUT", "PATCH", "DELETE"])
async def index(request):
    return raw(b"Welcome. Example>> http :8000/http.127.0.0.1:9000/home")
 
 
@app.route("/<full:path>", methods=["GET", "POST", "PUT", "PATCH", "DELETE"])
async def handler(request, full: str):
    host, url = full.lstrip("/"), ""
    if m := re.search(r"(https?)[^0-9a-zA-Z]+(.+)", host):
        scheme, host = m.groups()
    else:
        scheme = "https"
    try:
        domain, url = host.split("/", 1)
    except ValueError:
        domain = host
    base_url = scheme + "://" + domain
    target_path = url
    if qs := request.query_string:
        target_path += "?" + qs
    if not target_path:
        target_path = base_url
    if not target_path.startswith("/") and not target_path.startswith("http"):
        target_path = "/" + target_path
    logger.debug(f"{base_url=}; {target_path=}")
    async with AsyncClient(
        base_url=base_url, follow_redirects=True, timeout=20
    ) as client:
        method, body = request.method, request.body
        r = await client.request(method, target_path, content=body)
        if r.status_code == 302 and (next_url := r.headers.get("location")):
            r = await client.request(method, next_url, content=body)
    return raw(r.content, status=r.status_code)
 
 
if __name__ == "__main__":  # pragma: no cover
    app.run(debug=True, host="0.0.0.0")

Start in daemon:

gunicorn app:app --bind 0.0.0.0:9337 --worker-class uvicorn.workers.UvicornWorker --daemon
posted @ 2025-08-20 18:03  waketzheng  阅读(5)  评论(0)    收藏  举报