php脚本实现http代理服务


背景说明

就是为了实现的就是一个透传的功能,作为代理服务,除了参数之外,header信息在请求目标地址的时候也会带上。

php版本5.6+

需要开启curl扩展


代理地址

这个代理服务只有一个文件,我命名为proxy.php,部署在代理服务器的web下,比如通过 http://www.a.com/proxy.php访问。

如果你的前端是https访问,你又想访问一个http的接口的话,你可以给代理部署https,这样浏览器就不会报异常了。


代理说明

1. 支持http方法。GET,POST

2. 必填参数target_url(目标地址,即需要代理的地址)

3. 参数形式包括3种

    (1) Get参数

    (2) Post表单参数

    (3) 存放于header中 (自定义的参数部分首字母会转换成大写)

    (4) Post http body参数(json格式)

4. 请求目标地址时,代理会带上客户端请求代理的header信息,以及参数,然后输出返回。

找不到target_url参数或者参数非合法url时将返回错误信息,json格式,如:

{
    "code": 500,
    "msg": "无目标url信息",
    "data": []
}


使用举例

1. JSON请求体
POST /proxy.php HTTP/1.1
Host: 127.0.0.1
Content-Type: application/json
dadadada: 1313131
Cache-Control: no-cache

{"target_url":"http:\/\/www.b.com\/index.php","a":1}


2. POST方式
POST /proxy.php HTTP/1.1

Host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded
dadadada: 1313131
Cache-Control: no-cache

target_url=http%3A%2F%2Fwww.b.com%2Findex.php&company_code=1


3. GET方式
GET /proxy.php?target_url=http://www.b.com/index.php HTTP/1.1
Host: 127.0.0.1
dadadada: 1313131
Cache-Control: no-cache


完整代码

完整代码贴上,代码嘛就是抄来抄去的

<?php
error_reporting(0);
set_time_limit(10);

$target_url = getUrl();//获取目标url
$aAccess = curl_init();
curl_setopt($aAccess, CURLOPT_HTTPHEADER,getOutsideHeaders());
curl_setopt($aAccess, CURLOPT_HEADER, true);
curl_setopt($aAccess, CURLOPT_RETURNTRANSFER, true);
curl_setopt($aAccess, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($aAccess, CURLOPT_SSL_VERIFYPEER, false);  
curl_setopt($aAccess, CURLOPT_SSL_VERIFYHOST, false);  
curl_setopt($aAccess, CURLOPT_TIMEOUT, 60);
curl_setopt($aAccess, CURLOPT_BINARYTRANSFER, true);

if(!empty($_SERVER['HTTP_REFERER']))
    curl_setopt($aAccess,CURLOPT_REFERER,$_SERVER['HTTP_REFERER']);

if($_SERVER['REQUEST_METHOD']=='POST'){
    curl_setopt($aAccess, CURLOPT_POST, 1);
    $php_input = file_get_contents('php://input');
    //判断是否为json
    if(is_null(json_decode($php_input))){
        curl_setopt($aAccess, CURLOPT_POSTFIELDS, http_build_query($_POST));
    }else{
        curl_setopt($aAccess, CURLOPT_POSTFIELDS, $php_input);
    }
}elseif($_SERVER['REQUEST_METHOD']=='GET'){
    if($_GET){
        $url_arr = parse_url($target_url);
        if($url_arr['query']){
            $target_url = $target_url.'&'.http_build_query($_GET);
        }else{
            $target_url = $url_arr['scheme'].'://'.$url_arr['host'].$url_arr['path'].'/?'.http_build_query($_GET);
        }
    }
}

curl_setopt($aAccess, CURLOPT_URL, $target_url);
$sResponse = curl_exec($aAccess);
list($headerstr,$sResponse) = parseHeader($sResponse);
$headarr= explode("\r\n", $headerstr);
foreach($headarr as $h){
    if(strlen($h)>0){
        if(strpos($h,'Content-Length')!==false) continue;
        if(strpos($h,'Transfer-Encoding')!==false) continue;
        if(strpos($h,'Connection')!==false) continue;
        if(strpos($h,'HTTP/1.1 100 Continue')!==false) continue;
        header($h);
    }
}

function get_client_header(){
    $headers=array();
    foreach($_SERVER as $k=>$v){
        if(strpos($k,'HTTP_')===0){
            $k=strtolower(preg_replace('/^HTTP/', '', $k));
            $k=preg_replace_callback('/_\w/','header_callback',$k);
            $k=preg_replace('/^_/','',$k);
            $k=str_replace('_','-',$k);
            if($k=='Host') continue;
            $headers[]="$k:$v";
        }
    }
    return $headers;
}

function header_callback($str){
    return strtoupper($str[0]);
}

function parseHeader($sResponse){
    list($headerstr,$sResponse)=explode("\r\n\r\n",$sResponse, 2);
    $ret=array($headerstr,$sResponse);
    if(preg_match('/^HTTP\/1\.1 \d{3}/', $sResponse)){
        $ret=parseHeader($sResponse);
    }
    return $ret;
}

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;
      }
   } 
   return $headers;
 } 

function is_url($url){
    $r = "/http[s]?:\/\/[\w.]+[\w\/]*[\w.]*\??[\w=&\+\%]*/is";
    if(preg_match($r,$url)){
        return true;
    }
    return false;
}

/*
 * JSON方式输出
 */
function json_output($msg="",$code=500,$data=[]){
    header("Content-Type: application/json; charset=utf-8");
    header('Access-Control-Allow-Origin:*'); //*代表可访问的地址,可以设置指定域名
    header('Access-Control-Allow-Methods:POST,GET');
    exit(json_encode(array("code"=>$code,"msg"=>$msg,"data"=>$data),JSON_UNESCAPED_UNICODE));
}

function getUrl(){
    $target_url = urldecode($_REQUEST['target_url']);
    if(empty($target_url)) {
        //尝试去http body中获取
        $php_input = file_get_contents('php://input');
        if($php_input){
            $php_input = json_decode($php_input,true);
            if($php_input && is_array($php_input) && $php_input['target_url']){
                $target_url = $php_input['target_url'];
                if(!is_url($target_url)){
                    json_output('请输入合法的url信息');
                }
                return $target_url;
            }
        }
        json_output('无目标url信息');
    }
    if(!is_url($target_url)){
        json_output('请输入合法的url信息');
    }
    unset($_GET['target_url']);
    unset($_POST['target_url']);
    unset($_REQUEST['target_url']);
    return $target_url;
}
curl_close($aAccess);

header('Access-Control-Allow-Origin:*'); //*代表可访问的地址,可以设置指定域名
header('Access-Control-Allow-Methods:POST,GET');
echo $sResponse;


php http


上一篇:浅谈依赖注入与控制反转(转)

数据库小操作备忘:下一篇