It's gotten a bit more complex; The proxy handler didn't pass all the client headers to the proxy server. This caused problems with having the wrong client type, no Etag caching, cookie passing, etc. Here's the current rev, which solves a lot of these issues.
The cookie handling was broken because I wasn't using cookies on my back-end app. My SSO implementation was caching the cookies to the back-end server in the session.
So, here you go!
<?php
class ProxyHandler
{
private $url;
private $proxy_url;
private $proxy_host;
private $proxy_proto;
private $translated_url;
private $curl_handler;
private $cache_control=false;
private $pragma=false;
private $client_headers=array();
function __construct($url, $proxy_url)
{
// Strip the trailing '/' from the URLs so they are the same.
$this->url = preg_replace(',/$,','',$url);
$this->proxy_url = preg_replace(',/$,','',$proxy_url);
// Parse all the parameters for the URL
if (isset($_SERVER['PATH_INFO']))
{
$proxy_url .= $_SERVER['PATH_INFO'];
}
else
{
// Add the '/' at the end
$proxy_url .= '/';
}
if ($_SERVER['QUERY_STRING'] !== '')
{
$proxy_url .= "?{$_SERVER['QUERY_STRING']}";
}
$this->translated_url = $proxy_url;
$this->curl_handler = curl_init($this->translated_url);
// Set various options
$this->setCurlOption(CURLOPT_RETURNTRANSFER, true);
$this->setCurlOption(CURLOPT_BINARYTRANSFER, true); // For images, etc.
$this->setCurlOption(CURLOPT_USERAGENT,$_SERVER['HTTP_USER_AGENT']);
$this->setCurlOption(CURLOPT_WRITEFUNCTION, array($this,'readResponse'));
$this->setCurlOption(CURLOPT_HEADERFUNCTION, array($this,'readHeaders'));
// Process post data.
if (count($_POST))
{
// Empty the post data
$post=array();
// Set the post data
$this->setCurlOption(CURLOPT_POST, true);
// Encode and form the post data
foreach($_POST as $key=>$value)
{
$post[] = urlencode($key)."=".urlencode($value);
}
$this->setCurlOption(CURLOPT_POSTFIELDS, implode('&',$post));
unset($post);
}
elseif ($_SERVER['REQUEST_METHOD'] !== 'GET') // Default request method is 'get'
{
// Set the request method
$this->setCurlOption(CURLOPT_CUSTOMREQUEST, $_SERVER['REQUEST_METHOD']);
}
// Handle the client headers.
$this->handleClientHeaders();
}
public function setClientHeader($header)
{
$this->client_headers[] = $header;
}
// Executes the proxy.
public function execute()
{
$this->setCurlOption(CURLOPT_HTTPHEADER, $this->client_headers);
curl_exec($this->curl_handler);
}
// Get the information about the request.
// Should not be called before exec.
public function getCurlInfo()
{
return curl_getinfo($this->curl_handler);
}
// Sets a curl option.
public function setCurlOption($option, $value)
{
curl_setopt($this->curl_handler, $option, $value);
}
protected function readHeaders(&$cu, $string)
{
$length = strlen($string);
if (preg_match(',^Location:,', $string))
{
$string = str_replace($this->proxy_url, $this->url, $string);
}
elseif(preg_match(',^Cache-Control:,', $string))
{
$this->cache_control = true;
}
elseif(preg_match(',^Pragma:,', $string))
{
$this->pragma = true;
}
if (header !== "\r\n")
{
header(rtrim($string));
}
return $length;
}
protected function handleClientHeaders()
{
$headers = apache_request_headers();
foreach ($headers as $header => $value) {
switch($header)
{
case 'Host':
break;
default:
$this->setClientHeader(sprintf('%s: %s', $header, $value));
break;
}
}
}
protected function readResponse(&$cu, $string)
{
static $headersParsed = false;
// Clear the Cache-Control and Pragma headers
// if they aren't passed from the proxy application.
if ($headersParsed === false)
{
if (!$this->cache_control)
{
header('Cache-Control: ');
}
if (!$this->pragma)
{
header('Pragma: ');
}
$headersParsed = true;
}
$length = strlen($string);
echo $string;
return $length;
}
}
?>
Update: Added a google code project for php5rp at
Google Code and here's the
Subversion Link for downloading.