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