欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

PHP反向代理类代码

程序员文章站 2023-10-30 14:57:04
改自php reverse proxy prp,修改了原版中的一些错误,支持了文件上传以及上传文件类型识别,支持指定ip,自适应sae环境。 使用方法 <...

改自php reverse proxy prp,修改了原版中的一些错误,支持了文件上传以及上传文件类型识别,支持指定ip,自适应sae环境。

使用方法

<?php
$proxy=new phpreverseproxy();
$proxy->port="8080";
$proxy->host="www.jb51.net";
//$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;
 } 
 
}
?>