如何用 Python 实现网络请求转发

具体需求如下:

  1. 1 个服务器,多个客户端, 当服务器接受一个网络请求(如访问百度首页),将这个请求转发给某个客户端,客户端将请求的结果返回给服务器
  2. 要求百度看到的请求是来自于客户端的(特指 ip)

因为对网络这一块的知识了解的不多,不知需要哪些技术可以支持这个需求(有没有轮子可以用),请赐教= =


如何用 Python 实现网络请求转发
9 回复

1.DNS 做域名劫持,Nginx 做代理。
2.百度看到是代理服务器的地址。


用Python实现网络请求转发,核心是搭建一个代理服务器。最直接的方法是使用标准库的 http.server 模块,或者功能更强大的第三方库如 Flaskaiohttp。下面我提供一个基于 http.server 的基础示例,它清晰展示了转发的核心逻辑。

这个 ProxyHandler 会拦截请求,修改目标URL(这里是硬编码到 http://httpbin.org),然后代为请求并将响应原样返回给客户端。

from http.server import HTTPServer, BaseHTTPRequestHandler
import urllib.request
import urllib.parse

class ProxyHandler(BaseHTTPRequestHandler):
    # 目标服务器的基础URL
    TARGET_BASE = "http://httpbin.org"

    def do_GET(self):
        # 1. 构建目标URL
        target_url = urllib.parse.urljoin(self.TARGET_BASE, self.path)
        self.log_message(f"Forwarding GET to: {target_url}")

        # 2. 代为发起请求
        try:
            with urllib.request.urlopen(target_url) as response:
                # 3. 将目标服务器的状态码和头信息复制给客户端
                self.send_response(response.status)
                for key, value in response.headers.items():
                    self.send_header(key, value)
                self.end_headers()
                # 4. 将响应体数据流式传输回客户端
                self.wfile.write(response.read())
        except Exception as e:
            self.send_error(500, f"Proxy error: {str(e)}")

    # 同样处理POST等其他方法
    def do_POST(self):
        target_url = urllib.parse.urljoin(self.TARGET_BASE, self.path)
        content_length = int(self.headers.get('Content-Length', 0))
        post_data = self.rfile.read(content_length) if content_length else None

        self.log_message(f"Forwarding POST to: {target_url}")
        req = urllib.request.Request(target_url, data=post_data, method='POST')
        # 复制原始请求头(可选,可根据需要过滤)
        for key, value in self.headers.items():
            req.add_header(key, value)

        try:
            with urllib.request.urlopen(req) as response:
                self.send_response(response.status)
                for key, value in response.headers.items():
                    self.send_header(key, value)
                self.end_headers()
                self.wfile.write(response.read())
        except Exception as e:
            self.send_error(500, f"Proxy error: {str(e)}")

if __name__ == '__main__':
    server = HTTPServer(('localhost', 8888), ProxyHandler)
    print("Proxy server running on http://localhost:8888")
    server.serve_forever()

运行后,访问 http://localhost:8888/anything/foo,代理服务器会实际请求 http://httpbin.org/anything/foo 并将结果返回给你。

核心要点:

  1. 请求转发:在 do_GETdo_POST 等方法中,根据原始请求的路径 (self.path)、方法、头信息和体,构建一个新的请求发送到目标服务器。
  2. 响应回传:接收目标服务器的响应,将其状态码、头部和正文原样写回给原始客户端 (self.send_response, self.send_header, self.wfile.write)。
  3. 错误处理:用 try...except 包裹对目标服务器的请求,避免代理进程因目标服务器问题而崩溃。

对于生产环境,这个基础版本过于简单。你需要考虑连接池、超时控制、HTTPS支持、请求头过滤(避免循环或敏感信息泄露)、并发性能和认证等。这时可以考虑使用成熟的库:

  • 同步场景requests + Flask/FastAPI 是经典组合,易于控制和扩展。
  • 高并发异步场景aiohttphttpx 是更好的选择,能高效处理大量并发连接。

一句话建议:根据场景复杂度选择基础 http.server 或功能更全的 Flask/aiohttp 方案。

LZ 可以看一下这三个工具:
socat
haproxy
squid

先说清楚 你是要转发哪一层

我仿佛闻到了了黑产的味道…

这种东西一般黑产自己开发的,因为能有这种需求的一般都见不得光。

spring 就可以了啊,服务端 controller 接收请求,restTemplate 封装,发送到客户端 controller,客户端封装后请求真实服务器,返回结果返回给服务端,服务端再返回给客户端。

这不就是代理吗?^O^轮子的话随便找个代理软件就行了…甚至有专门卖代理池的,都不需要你搭客户端

又可以解释“为什么浏览器要限制跨域请求”了。如果没有跨域限制,网站可以把在线访客当成代理资源使用。就像楼主这种需求,一个 web 页面就能实现。那样互联网就乱套了。

你想干什么坏事,哈哈!

回到顶部