PHP反向代理类代码


Posted in PHP onAugust 15, 2014

改自PHP Reverse Proxy PRP,修改了原版中的一些错误,支持了文件上传以及上传文件类型识别,支持指定IP,自适应SAE环境。

使用方法

<?php
$proxy=new PhpReverseProxy();
$proxy->port="8080";
$proxy->host="3water.com";
//$proxy->ip="1.1.1.1";
$proxy->forward_path="";
$proxy->connect();
$proxy->output();
?>

源代码

<?php
//Source Code: http://www.xiumu.org/technology/php-reverse-proxy-class.shtml
class PhpReverseProxy{
 public $publicBaseURL;
 public $outsideHeaders;
 public $XRequestedWith;
 public $sendPost;
 public $port,$host,$ip,$content,$forward_path,$content_type,$user_agent,
  $XFF,$request_method,$IMS,$cacheTime,$cookie,$authorization;
 private $http_code,$lastModified,$version,$resultHeader;
 const chunkSize = 10000;
 function __construct(){
  $this->version="PHP Reverse Proxy (PRP) 1.0";
  $this->port="8080";
  $this->host="127.0.0.1";
  $this->ip="";
  $this->content="";
  $this->forward_path="";
  $this->path="";
  $this->content_type="";
  $this->user_agent="";
  $this->http_code="";
  $this->XFF="";
  $this->request_method="GET";
  $this->IMS=false;
  $this->cacheTime=72000;
  $this->lastModified=gmdate("D, d M Y H:i:s",time()-72000)." GMT";
  $this->cookie="";
  $this->XRequestedWith = "";
  $this->authorization = "";
 }
 function translateURL($serverName) {
  $this->path=$this->forward_path.$_SERVER['REQUEST_URI'];
  if(IS_SAE)
   return $this->translateServer($serverName).$this->path;
  if($_SERVER['QUERY_STRING']=="")
   return $this->translateServer($serverName).$this->path;
  else
  return $this->translateServer($serverName).$this->path."?".$_SERVER['QUERY_STRING'];
 }
 function translateServer($serverName) {
  $s = empty($_SERVER["HTTPS"]) ? ''
   : ($_SERVER["HTTPS"] == "on") ? "s"
   : "";
  $protocol = $this->left(strtolower($_SERVER["SERVER_PROTOCOL"]), "/").$s;
  if($this->port=="") 
   return $protocol."://".$serverName;
  else
   return $protocol."://".$serverName.":".$this->port;
 }
 function left($s1, $s2) {
  return substr($s1, 0, strpos($s1, $s2));
 }
 function preConnect(){
  $this->user_agent=$_SERVER['HTTP_USER_AGENT'];
  $this->request_method=$_SERVER['REQUEST_METHOD'];
  $tempCookie="";
  foreach ($_COOKIE as $i => $value) {
   $tempCookie=$tempCookie." $i=$_COOKIE[$i];";
  }
  $this->cookie=$tempCookie;
  if(empty($_SERVER['HTTP_X_FORWARDED_FOR'])){
   $this->XFF=$_SERVER['REMOTE_ADDR'];
  } else {
   $this->XFF=$_SERVER['HTTP_X_FORWARDED_FOR'].", ".$_SERVER['REMOTE_ADDR'];
  }
 
 }
 function connect(){
  if(empty($_SERVER['HTTP_IF_MODIFIED_SINCE'])){
   $this->preConnect();
   $ch=curl_init();
   if($this->request_method=="POST"){
    curl_setopt($ch, CURLOPT_POST,1);
 
    $postData = array();
    $filePost = false;
    $uploadPath = 'uploads/';
    if (IS_SAE)
      $uploadPath = SAE_TMP_PATH;
 
    if(count($_FILES)>0){
      if(!is_writable($uploadPath)){
        die('You cannot upload to the specified directory, please CHMOD it to 777.');
      }
      foreach($_FILES as $key => $fileArray){ 
        copy($fileArray["tmp_name"], $uploadPath . $fileArray["name"]);
        $proxyLocation = "@" . $uploadPath . $fileArray["name"] . ";type=" . $fileArray["type"];
        $postData = array($key => $proxyLocation);
        $filePost = true;
      }
    }
 
    foreach($_POST as $key => $value){
      if(!is_array($value)){
     $postData[$key] = $value;
      }
      else{
     $postData[$key] = serialize($value);
      }
    }
 
    if(!$filePost){
      //$postData = http_build_query($postData);
      $postString = "";
      $firstLoop = true;
      foreach($postData as $key => $value){
      $parameterItem = urlencode($key)."=".urlencode($value);
      if($firstLoop){
     $postString .= $parameterItem;
      }
      else{
     $postString .= "&".$parameterItem;
      }
      $firstLoop = false; 
      }
      $postData = $postString;
    }
 
    //echo print_r($postData);
 
    //curl_setopt($ch, CURLOPT_VERBOSE, 0);
    //curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    //curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible;)");
    $this->sendPost = $postData;
    //var_dump(file_exists(str_replace('@','',$postData['imgfile'])));exit;
    curl_setopt($ch, CURLOPT_POSTFIELDS,$postData);
    //curl_setopt($ch, CURLOPT_POSTFIELDS,file_get_contents($proxyLocation));
    //curl_setopt($ch, CURLOPT_POSTFIELDS,file_get_contents("php://input"));
   }
 
   //gets rid of mulitple ? in URL
   $translateURL = $this->translateURL(($this->ip)?$this->ip:$this->host);
   if(substr_count($translateURL, "?")>1){
     $firstPos = strpos($translateURL, "?", 0);
     $secondPos = strpos($translateURL, "?", $firstPos + 1);
     $translateURL = substr($translateURL, 0, $secondPos);
   }
 
   curl_setopt($ch,CURLOPT_URL,$translateURL);
 
   $proxyHeaders = array(
     "X-Forwarded-For: ".$this->XFF,
     "User-Agent: ".$this->user_agent,
     "Host: ".$this->host
   );
 
   if(strlen($this->XRequestedWith)>1){
     $proxyHeaders[] = "X-Requested-With: ".$this->XRequestedWith;
     //echo print_r($proxyHeaders);
   }
 
   curl_setopt($ch,CURLOPT_HTTPHEADER, $proxyHeaders);
 
   if($this->cookie!=""){
    curl_setopt($ch,CURLOPT_COOKIE,$this->cookie);
   }
   curl_setopt($ch,CURLOPT_FOLLOWLOCATION,false); 
   curl_setopt($ch,CURLOPT_AUTOREFERER,true); 
   curl_setopt($ch,CURLOPT_HEADER,true);
   curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
 
   $output=curl_exec($ch);
   $info = curl_getinfo( $ch );
   curl_close($ch);
   $this->postConnect($info,$output);
  }else {
   $this->lastModified=$_SERVER['HTTP_IF_MODIFIED_SINCE'];
   $this->IMS=true;
  }
 }
 function postConnect($info,$output){
  $this->content_type=$info["content_type"];
  $this->http_code=$info['http_code'];
  //var_dump($info);exit;
  if(!empty($info['last_modified'])){
   $this->lastModified=$info['last_modified'];
  }
  $this->resultHeader=substr($output,0,$info['header_size']);
  $content = substr($output,$info['header_size']);
 
  if($this->http_code=='200'){
   $this->content=$content;
  }elseif( ($this->http_code=='302' || $this->http_code=='301') && isset($info['redirect_url'])){
   $redirect_url = str_replace($this->host,$_SERVER['HTTP_HOST'],$info['redirect_url']);
   if (IS_SAE)
     $redirect_url = str_replace('http://fetchurl.sae.sina.com.cn/','',$info['redirect_url']);
   header("Location: $redirect_url");
   exit;
  }elseif($this->http_code=='404'){
   header("HTTP/1.1 404 Not Found");
   exit("HTTP/1.1 404 Not Found");
  }elseif($this->http_code=='500'){
   header('HTTP/1.1 500 Internal Server Error');
   exit("HTTP/1.1 500 Internal Server Error");
  }else{
   exit("HTTP/1.1 ".$this->http_code." Internal Server Error");
  }
 }
 
 function output(){
  $currentTimeString=gmdate("D, d M Y H:i:s",time());
  $expiredTime=gmdate("D, d M Y H:i:s",(time()+$this->cacheTime));
 
  $doOriginalHeaders = true;
  if($doOriginalHeaders){
    if($this->IMS){
     header("HTTP/1.1 304 Not Modified");
     header("Date: Wed, $currentTimeString GMT");
     header("Last-Modified: $this->lastModified");
     header("Server: $this->version");
    }else{
 
     header("HTTP/1.1 200 OK");
     header("Date: Wed, $currentTimeString GMT");
     header("Content-Type: ".$this->content_type);
     header("Last-Modified: $this->lastModified");
     header("Cache-Control: max-age=$this->cacheTime");
     header("Expires: $expiredTime GMT");
     header("Server: $this->version");
     preg_match("/Set-Cookie:[^\n]*/i",$this->resultHeader,$result);
     foreach($result as $i=>$value){
      header($result[$i]);
     }
     preg_match("/Content-Encoding:[^\n]*/i",$this->resultHeader,$result);
     foreach($result as $i=>$value){
      //header($result[$i]);
     }
     preg_match("/Transfer-Encoding:[^\n]*/i",$this->resultHeader,$result);
     foreach($result as $i=>$value){
      //header($result[$i]);
     }
     echo($this->content);
     /*
     if(stristr($this->content, "error")){
    echo print_r($this->sendPost);
     }
     */
    }
  }
  else{
    $headerString = $this->resultHeader; //string 
    $headerArray = explode("\n", $headerString);
    foreach($headerArray as $privHeader){
   header($privHeader);
    }
 
    if(stristr($headerString, "Transfer-encoding: chunked")){
   flush();
   ob_flush();
   $i = 0;
   $maxLen = strlen($this->content);
 
   while($i < $maxLen){
     $endChar = $i + self::chunkSize;
     if($endChar >= $maxLen){
    $endChar = $maxLen - 1;
     }
     $chunk = substr($this->content, $i, $endChar);
     $this->dump_chunk($chunk);
     flush();
     ob_flush();
     $i = $i + $endChar;
   }
    }
    else{
    echo($this->content);
    }
 
    //echo "header: ".print_r($headerArray);
    //header($this->resultHeader);
  }
 
 }
 
 
 function dump_chunk($chunk) {
   echo sprintf("%x\r\n", strlen($chunk));
   echo $chunk;
   echo "\r\n";
 }
 
 
 function getOutsideHeaders(){
   $headers = array();
   foreach ($_SERVER as $name => $value){ 
  if (substr($name, 0, 5) == 'HTTP_') { 
    $name = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5))))); 
    $headers[$name] = $value; 
  }elseif ($name == "CONTENT_TYPE") { 
    $headers["Content-Type"] = $value; 
  }elseif ($name == "CONTENT_LENGTH") { 
    $headers["Content-Length"] = $value; 
  }elseif(stristr($name, "X-Requested-With")) { 
    $headers["X-Requested-With"] = $value;
    $this->XRequestedWith = $value;
  }
   } 
 
   //echo print_r($headers);
 
   $this->outsideHeaders = $headers;
   return $headers;
 } 
 
}
?>
PHP 相关文章推荐
不用数据库的多用户文件自由上传投票系统(2)
Oct 09 PHP
windows下PHP APACHE MYSQ完整配置
Jan 02 PHP
深入密码加salt原理的分析
Jun 06 PHP
PHP数据类型的总结分析
Jun 13 PHP
mac下安装nginx和php
Nov 04 PHP
php 过滤英文标点符号及过滤中文标点符号代码
Jun 12 PHP
PHP自动重命名文件实现方法
Nov 04 PHP
PHP文件上传、客户端和服务器端加限制、抓取错误信息、完整步骤解析
Jan 12 PHP
解决PHP上传非标准格式的图片pjpeg失败的方法
Mar 12 PHP
php分页查询mysql结果的base64处理方法示例
May 18 PHP
PHP空值检测函数与方法汇总
Nov 19 PHP
PHP crypt()函数的用法讲解
Feb 15 PHP
ThinkPHP中自定义目录结构的设置方法
Aug 15 #PHP
win7 64位系统 配置php最新版开发环境(php+Apache+mysql)
Aug 15 #PHP
php获取apk包信息的方法
Aug 15 #PHP
phpmyadmin出现Cannot start session without errors问题解决方法
Aug 14 #PHP
PHP解码unicode编码的中文字符代码分享
Aug 13 #PHP
使用ob系列函数实现PHP网站页面静态化
Aug 13 #PHP
PHP语法自动检查的Vim插件
Aug 11 #PHP
You might like
网友原创的PHP模板类代码
2008/09/07 PHP
PHP实现提取一个图像文件并在浏览器上显示的代码
2012/10/06 PHP
php牛逼的面试题分享
2013/01/18 PHP
php实现mysql封装类示例
2014/05/07 PHP
PHP的几个常用加密函数
2016/02/03 PHP
PHP CURL与java http使用方法详解
2018/01/26 PHP
体验js中splice()的强大(插入、删除或替换数组的元素)
2013/01/16 Javascript
控制页面按钮在后台执行期间不重复提交的JS方法
2013/06/24 Javascript
jQuery实现输入框下拉列表树插件特效代码分享
2015/08/27 Javascript
json传值以及ajax接收详解
2016/05/24 Javascript
ng-alain表单使用方式详解
2018/07/10 Javascript
JavaScript中构造函数与原型链之间的关系详解
2019/02/25 Javascript
微信小程序如何使用云开发
2019/05/17 Javascript
linux系统使用python获取内存使用信息脚本分享
2014/01/15 Python
Python Web框架Flask中使用新浪SAE云存储实例
2015/02/08 Python
深入理解Python中各种方法的运作原理
2015/06/15 Python
详解python中的模块及包导入
2019/08/30 Python
手把手教你Python yLab的绘制折线图的画法
2019/10/23 Python
Python xlwt模块使用代码实例
2020/06/10 Python
使用K.function()调试keras操作
2020/06/17 Python
canvas之自定义头像功能实现代码示例
2017/09/29 HTML / CSS
HTML5实现桌面通知 提示功能
2017/10/11 HTML / CSS
世界汽车零件:World Car Parts
2019/09/04 全球购物
匡威西班牙官网:Converse西班牙
2019/10/01 全球购物
Michael Kors澳大利亚官网:世界知名的奢侈饰品和成衣设计师
2020/02/13 全球购物
说说在weblogic中开发消息Bean时的persistent与non-persisten的差别
2013/04/07 面试题
迷你西餐厅创业计划书范文
2013/12/31 职场文书
手机促销活动方案
2014/02/05 职场文书
住宅质量保证书
2014/04/29 职场文书
医院院务公开实施方案
2014/05/03 职场文书
计算机科学技术自荐信
2014/06/12 职场文书
ktv好的活动方案
2014/08/15 职场文书
师德师风自我评价范文
2014/09/11 职场文书
2015大学生暑假调查报告
2015/07/13 职场文书
Python+Selenium实现读取网易邮箱验证码
2022/03/13 Python
oracle数据库去除重复数据
2022/05/20 Oracle