代码之家  ›  专栏  ›  技术社区  ›  Paul Tarjan

php:代理另一个url

  •  7
  • Paul Tarjan  · 技术社区  · 16 年前

    我有一个 mod_rewrite 将任何子域请求发送到php脚本的规则,该脚本应将这些请求代理到另一个主机(内部代理,而不是302)。

    我很接近,因为我的脚本可以与web浏览器一起工作,但是curl看起来不像:

    curl: (56) Received problem 2 in the chunky parser
    

    这是我的修改:

    RewriteCond %{HTTP_HOST} ^(.*)\.example\.com$
    RewriteRule ^.*$ %{DOCUMENT_ROOT}/proxy.php?__path=%1 [QSA,L]
    

    还有我的 proxy.php

    <?php
    
    $name = $_GET['__path'];
    unset($_GET['__path']);
    $path = $_SERVER['REQUEST_URI'];
    
    $url = "http://$name.internal.example.com$path";
    $ch = curl_init($url);
    $headers = array();
    foreach (apache_request_headers() as $key => $value) {
        $headers[] = "$key: $value";
    }
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $_SERVER['REQUEST_METHOD']);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($_POST));
    curl_setopt($ch, CURLOPT_HEADER, TRUE);  
    
    $data = curl_exec($ch);
    
    list($headers, $body) = explode("\r\n\r\n", $data, 2);
    $headers = explode("\r\n", $headers);
    foreach ($headers as $header) {
        header($header);
    }
    die($body);
    

    为什么curl不喜欢这个,但是浏览器可以接受它?

    编辑: 如果我不把 Transfer-Encoding: chunked 头,一切正常(因为我正在代理完整的请求,分块是不可能的)。接下来的一个问题是:我可以充当一个真正的中间人,在通过套接字获取数据时发送数据吗?

    1 回复  |  直到 16 年前
        1
  •  3
  •   rook    16 年前

    是的,你应该可以通过网络发送数据。但我怀疑您的问题可能源于持久的http连接。htp1.0将在请求之后断开连接,在代码中,您将为每个请求创建一个新的curl句柄,它更像http/1.0,而不是默认的http/1.1

    curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
    

    您可能仍然对应用程序层有问题,因为curl不打算像这样充当代理。另一种方法是修改现有的 PHP HTTP Client 并确保转发的请求足够接近您的需要。

    无论您使用什么方法,我强烈建议使用wireshark进行调试。然后可以转储2个http请求,然后使用 Meld 找出差异。

    推荐文章