Skip to content

Instantly share code, notes, and snippets.

@seebz
Created February 11, 2013 13:42
Show Gist options
  • Select an option

  • Save seebz/4754475 to your computer and use it in GitHub Desktop.

Select an option

Save seebz/4754475 to your computer and use it in GitHub Desktop.
PHP mod_proxy
<?php
// .Htacesss
// ---------
/*
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteRule .* proxy.php [L]
</IfModule>
*/
// Settings (require php5.3)
// ----------------------------------------------------------------------------
$target_ip = '123.123.123.123';
$target_domain = false; // Si différent de la requête
$target_path = false; // Si différent de la requête
// ----------------------------------------------------------------------------
// Analyse de la requête client
// ----------------------------------------------------------------------------
$request_headers = request_headers();
$request_method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET';
$request_protocol = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on' ? 'https' : 'http');
$request_domain = $_SERVER['HTTP_HOST'];
$request_path = $_SERVER['REQUEST_URI'];
$target_url = $request_protocol . '://'
. ($target_ip ?: ($target_domain ?: $request_domain))
. ($target_path ?: $request_path);
if ($target_domain)
{
$request_headers['Host'] = $target_domain;
}
if (isset($request_headers['Accept-Encoding'])) unset($request_headers['Accept-Encoding']);
if (isset($request_headers['Content-Length'])) unset($request_headers['Content-Length']);
// Post data
$request_post_fields = $_POST;
// Uploads
if ($_FILES)
{
$UPLOADS = convert_files_var($_FILES);
$request_post_fields += $UPLOADS;
$request_headers['Content-Type'] = 'multipart/form-data';
}
// Requête distante
// ----------------------------------------------------------------------------
$params = array(
'url' => $target_url,
'headers' => $request_headers,
'method' => $request_method,
'post_fields' => http_build_query_for_curl($request_post_fields),
);
$cr = new CurlRequest($params);
$response = $cr->exec();
// Curl error
if ($response['curl_error'])
{
header('Status: 500');
die ($response['curl_error']);
}
// Traitement de la réponse
$response_http_code = $response['http_code'];
$response_headers = $response['headers'];
$response_body = $response['body'];
// Réponse (headers)
$ignore = array('Transfer-Encoding', 'Content-Length');
$pattern = sprintf('`^(%s)`i', implode('|', $ignore));
foreach($response_headers as $i => $h) {
if ( ! preg_match($pattern, $h))
header($h);
}
header("Status: {$response_http_code}", true, $response_http_code);
header("X-Forwarded-For: {$_SERVER['REMOTE_ADDR']}");
header('X-Forwarded-Host: '. ($target_domain ?: $_SERVER['HTTP_HOST']));
header("X-Forwarded-Server: {$_SERVER['HTTP_HOST']}");
// Réponse (body)
echo $response_body;
// Fonctions utiles
// ----------------------------------------------------------------------------
/**
* Fetch all HTTP request headers
* @link http://php.net/manual/en/function.apache-request-headers.php
* @return array An associative array of all the HTTP headers in the current request, or FALSE on failure.
*/
function request_headers()
{
if (function_exists('apache_request_headers')) {
return apache_request_headers();
}
foreach($_SERVER as $k => $v)
{
if (substr($k, 0, 5) == 'HTTP_')
{
$k = str_replace('_', ' ', substr($k, 5));
$k = ucwords(strtolower($k));
$k = str_replace(' ', '-', $k);
$out[$k] = $v;
}
}
if (isset($_SERVER['CONTENT_TYPE']))
$out['Content-Type'] = $_SERVER['CONTENT_TYPE'];
if (isset($_SERVER['CONTENT_LENGTH']))
$out['Content-Length'] = $_SERVER['CONTENT_LENGTH'];
if (isset($out['Remote-Ip']))
unset($out['Remote-Ip']);
return $out;
}
/**
* Converts $_FILES var to logical array
*
* $UPLOADS = convert_files_var($_FILES);
*/
function convert_files_var(array $in)
{
$out = $in;
foreach ($out as $key => $v)
{
if (is_array($v['name']))
{
$v_convert = array();
$v_keys = array_keys($v['name']);
foreach($v_keys as $v_k)
{
$v_convert[$v_k] = array(
'name' => $v['name'][$v_k],
'type' => $v['type'][$v_k],
'tmp_name' => $v['tmp_name'][$v_k],
'error' => $v['error'][$v_k],
'size' => $v['size'][$v_k],
);
}
$out[$key] = call_user_func(__FUNCTION__, $v_convert);
}
}
return $out;
}
// http://stackoverflow.com/a/8224117
function http_build_query_for_curl($query_data, &$new = array(), $prefix = null )
{
if (is_object($query_data))
{
$query_data = get_object_vars($query_data);
}
foreach ($query_data AS $key => $value)
{
$k = isset($prefix) ? $prefix . '[' . $key . ']' : $key;
if (is_array($value) OR is_object($value))
{
//http_build_query_for_curl( $value, $new, $k );
$func = __FUNCTION__;
$func($value, $new, $k);
}
else
{
$new[$k] = $value;
}
}
return $new;
}
class CurlRequest {
private $ch;
private $options = array(
'RETURNTRANSFER' => true,
'HEADER' => true,
'FOLLOWLOCATION' => false,
'SSL_VERIFYPEER' => false,
'SSL_VERIFYHOST' => false,
'TIMEOUT' => 5,
);
/**
* Init curl session
*
* $params = array('url' => '',
* 'host' => '',
* 'header' => '',
* 'method' => '',
* 'referer' => '',
* 'cookie' => '',
* 'post_fields' => '',
* ['login' => '',]
* ['password' => '',]
* 'timeout' => 0
* );
*/
public function __construct($params) {
$this->ch = curl_init();
// Options
foreach ($this->options as $key => $value) {
$constant = 'CURLOPT_' . $key;
if (defined($constant)) {
@curl_setopt($this->ch, constant($constant), $value);
}
}
// Url
@curl_setopt($this->ch, CURLOPT_URL, $params['url']);
// Headers
$headers = array();
foreach($params['headers'] as $k => $v) {
$headers[] = $k . ': ' . $v;
}
@curl_setopt($this->ch, CURLOPT_HTTPHEADER, $headers);
switch(strtoupper($params['method'])) {
case 'HEAD':
@curl_setopt($this -> ch,CURLOPT_NOBODY, true);
break;
case 'POST':
curl_setopt($this->ch, CURLOPT_POST, true);
//curl_setopt($this->ch, CURLOPT_POSTFIELDS, http_build_query($_POST));
$post_fields = ($params['post_fields'] ?: array());
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $post_fields);
break;
}
// Ne fonctionne plus depuis PHP 4.3.0
if (isset($_SERVER['PHP_AUTH_USER']) & isset($_SERVER['PHP_AUTH_PW'])) {
@curl_setopt($this->ch, CURLOPT_USERPWD, $_SERVER['PHP_AUTH_USER'].':'.$_SERVER['PHP_AUTH_PW']);
}
}
/**
* Make curl request
*
* @return array 'header','body','curl_error','http_code','last_url'
*/
public function exec() {
$response = curl_exec($this->ch);
$error = curl_error($this->ch);
$result = array(
'header' => '',
'body' => '',
'curl_error' => '',
'http_code' => '',
'last_url' => '',
);
if ( $error ) {
$result['curl_error'] = $error;
return $result;
}
$header_size = curl_getinfo($this->ch,CURLINFO_HEADER_SIZE);
$headers = trim(substr($response, 0, $header_size));
$headers = explode("\n", $headers);
if (stripos($headers[0], 'HTTP/1')===0) {
unset($headers[0]);
}
$result = array(
'headers' => $headers,
'body' => substr( $response, $header_size ),
'curl_error' => '',
'http_code' => curl_getinfo($this -> ch,CURLINFO_HTTP_CODE),
'last_url' => curl_getinfo($this -> ch,CURLINFO_EFFECTIVE_URL),
);
return $result;
}
}
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment