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;
}
}
?>