2010-03-04 23 views
7

Tengo una regla mod_rewrite que enviará las solicitudes de subdominios a una secuencia de comandos php que debe proxy esas solicitudes a otro host (proxy interno, no 302).PHP: Proxy otra url

estoy cerca, en la que mi script funciona con los navegadores web, pero rizo no parece que:

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

Aquí es mi mod_rewrite:

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

Y mi 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); 

Cualquier razón por la que a Curl no le gusta esto pero los navegadores están bien con eso?

EDIT: Parece que si no envío de la cabecera Transfer-Encoding: chunked, todo está bien (ya que estoy proxy la solicitud completa, fragmentación no es posible). Entonces, una pregunta de seguimiento: ¿puedo actuar como un verdadero intermediario y enviar los datos a medida que los obtengo a través del socket?

Respuesta

3

Sí, debería poder enviar datos a través de la red a medida que lo obtiene. Pero sospecho que su problema puede provenir de conexiones HTTP persistentes. HTTP 1.0 se romperá la conexión después de la solicitud, en el código va a crear un nuevo recurso CURL para cada solicitud, lo que es más como HTTP/1.0 en lugar del predeterminado HTTP/1,1

curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); 

Usted todavía puede tener problemas con la capa de aplicación porque CURL no pretende actuar como un proxy como este. Otro enfoque sería modificar un existente PHP HTTP Client y asegurarse de que las solicitudes reenviadas sean lo suficientemente cercanas para sus necesidades.

Independientemente del enfoque que utilice, le recomiendo usar WireShark para la depuración. A continuación, puede volcar 2 solicitudes HTTP y luego usar algo como Meld para seleccionar las diferencias.