PHP反向代理类代码
改自PHPReverseProxyPRP,修改了原版中的一些错误,支持了文件上传以及上传文件类型识别,支持指定IP,自适应SAE环境。
使用方法
<?php $proxy=newPhpReverseProxy(); $proxy->port="8080"; $proxy->host="www.nhooo.com"; //$proxy->ip="1.1.1.1"; $proxy->forward_path=""; $proxy->connect(); $proxy->output(); ?>
源代码
<?php //SourceCode:http://www.xiumu.org/technology/php-reverse-proxy-class.shtml classPhpReverseProxy{ 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; constchunkSize=10000; function__construct(){ $this->version="PHPReverseProxy(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,dMYH:i:s",time()-72000)."GMT"; $this->cookie=""; $this->XRequestedWith=""; $this->authorization=""; } functiontranslateURL($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']; } functiontranslateServer($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; } functionleft($s1,$s2){ returnsubstr($s1,0,strpos($s1,$s2)); } functionpreConnect(){ $this->user_agent=$_SERVER['HTTP_USER_AGENT']; $this->request_method=$_SERVER['REQUEST_METHOD']; $tempCookie=""; foreach($_COOKIEas$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']; } } functionconnect(){ 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('Youcannotuploadtothespecifieddirectory,pleaseCHMODitto777.'); } foreach($_FILESas$key=>$fileArray){ copy($fileArray["tmp_name"],$uploadPath.$fileArray["name"]); $proxyLocation="@".$uploadPath.$fileArray["name"].";type=".$fileArray["type"]; $postData=array($key=>$proxyLocation); $filePost=true; } } foreach($_POSTas$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($postDataas$key=>$value){ $parameterItem=urlencode($key)."=".urlencode($value); if($firstLoop){ $postString.=$parameterItem; } else{ $postString.="&".$parameterItem; } $firstLoop=false; } $postData=$postString; } //echoprint_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")); } //getsridofmulitple?inURL $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; //echoprint_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; } } functionpostConnect($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.1404NotFound"); exit("HTTP/1.1404NotFound"); }elseif($this->http_code=='500'){ header('HTTP/1.1500InternalServerError'); exit("HTTP/1.1500InternalServerError"); }else{ exit("HTTP/1.1".$this->http_code."InternalServerError"); } } functionoutput(){ $currentTimeString=gmdate("D,dMYH:i:s",time()); $expiredTime=gmdate("D,dMYH:i:s",(time()+$this->cacheTime)); $doOriginalHeaders=true; if($doOriginalHeaders){ if($this->IMS){ header("HTTP/1.1304NotModified"); header("Date:Wed,$currentTimeStringGMT"); header("Last-Modified:$this->lastModified"); header("Server:$this->version"); }else{ header("HTTP/1.1200OK"); header("Date:Wed,$currentTimeStringGMT"); header("Content-Type:".$this->content_type); header("Last-Modified:$this->lastModified"); header("Cache-Control:max-age=$this->cacheTime"); header("Expires:$expiredTimeGMT"); header("Server:$this->version"); preg_match("/Set-Cookie:[^\n]*/i",$this->resultHeader,$result); foreach($resultas$i=>$value){ header($result[$i]); } preg_match("/Content-Encoding:[^\n]*/i",$this->resultHeader,$result); foreach($resultas$i=>$value){ //header($result[$i]); } preg_match("/Transfer-Encoding:[^\n]*/i",$this->resultHeader,$result); foreach($resultas$i=>$value){ //header($result[$i]); } echo($this->content); /* if(stristr($this->content,"error")){ echoprint_r($this->sendPost); } */ } } else{ $headerString=$this->resultHeader;//string $headerArray=explode("\n",$headerString); foreach($headerArrayas$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); } } functiondump_chunk($chunk){ echosprintf("%x\r\n",strlen($chunk)); echo$chunk; echo"\r\n"; } functiongetOutsideHeaders(){ $headers=array(); foreach($_SERVERas$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; } } //echoprint_r($headers); $this->outsideHeaders=$headers; return$headers; } } ?>