Single

基于访客位置的301跳转-PHP实现

最近为自己高中建设毕业典礼视频站时,遇到了视频播放卡顿的问题,因为访客的地区分布较广,如果使用单一视频服务器,那么总有某些地区因为访问速度问题会导致体验不佳,在之前我使用阿里云的DNS进行按照地区将同一个域名分别指向到国内和国外两台服务器上面,以实现基于地理位置的就近拉取视频,但是这个样有很多的弊端,一个是比较浪费服务器,每个要跳转的地区都要有单独一台服务器接受访问并直接返回内容或者进行301跳转,二是维护的时候比较繁琐。

作为刚刚接触PHP的人,由于对其它编程语言比较熟悉,一开始计划了用Javascript或者PHP来写这个功能,但是由于Javascript的跳转很难做到301跳转,很多内嵌的资源比如内嵌图片和视频会遇到麻烦,使用PHP进行301跳转可以提高兼容性,所以最终选择了使用PHP来实现此功能

这是我的第一个PHP页面,使用了IP-Geolocation 提供的API来判断访客的具体位置,然后返回相应的跳转目标,同时加入了一些检测语句防止API失效或者访客IP地址获取失败。

代码如下:

<?php
	header('Cache-Control:no-cache,must-revalidate');  
	header('Pragma:no-cache');  
    $apiKey = "API_ACCESS_TOKEN";   //填写IP-Geolocation申请到的密钥
    $ipaddr = get_client_ip();   //使用IP-Geolocation API获取包括了访客信息的数组
    echo "Your IP Address:";   //在无参数时返回一个简易的信息页面
    echo $ipaddr;
	$location = get_geolocation($apiKey, $ipaddr);
    $decodedLocation = json_decode($location, true);
    $item = $_GET['item'];
    $flagaddr = $decodedLocation['country_flag'];
    $node_location = $decodedLocation['continent_code'];
    echo "<br>";
    echo "你来自于:";
    echo $decodedLocation['continent_name'];
    if ($node_location == ""){
    	echo "API接入失败";
    	$node_location = "AS";   //如果API失效,将返回亚太地区节点地址
    }
    echo "<br>当前最近节点: ";
    echo $node_location;
    if ($item == "flag"){    //返回当前访客地区的国旗,为IP-Geolocation内建功能
    	 Header("HTTP/1.1 301 Mved Permanently");
		 Header("Location: $flagaddr");
    } else if ($node_location == 'AS' and $item != "") {
         echo "<br>你来自亚太地区";
         Header("HTTP/1.1 301 Moved Permanently");
		 Header("Location: https://大陆服务器地址/$item");
    } else if ($node_location != 'AS' and $item != "") {
         echo "<br>你来自非亚太地区";
         Header("HTTP/1.1 301 Moved Permanently");
		 Header("Location: http://海外服务器地址/$item");
    } else {
    	echo "<br>请传入item请求参数使用<br>";
    }
     //以下为Geo-Location提供的SDK以及获取当前访客IP的函数。
   function get_geolocation($apiKey, $ipaddr, $lang = "en", $fields = "*", $excludes = "") {
        $url = "https://api.ipgeolocation.io/ipgeo?apiKey=".$apiKey."&ip=".$ipaddr."&lang=".$lang."&fields=".$fields."&excludes=".$excludes;
        $cURL = curl_init();
        curl_setopt($cURL, CURLOPT_URL, $url);
        curl_setopt($cURL, CURLOPT_HTTPGET, true);
        curl_setopt($cURL, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($cURL, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json',
            'Accept: application/json'
        ));
        return curl_exec($cURL);
    }
   function get_client_ip() {
    $ipaddress = '';
    if (getenv('HTTP_CLIENT_IP'))
        $ipaddress = getenv('HTTP_CLIENT_IP');
    else if(getenv('HTTP_X_FORWARDED_FOR'))
        $ipaddress = getenv('HTTP_X_FORWARDED_FOR');
    else if(getenv('HTTP_X_FORWARDED'))
        $ipaddress = getenv('HTTP_X_FORWARDED');
    else if(getenv('HTTP_FORWARDED_FOR'))
        $ipaddress = getenv('HTTP_FORWARDED_FOR');
    else if(getenv('HTTP_FORWARDED'))
       $ipaddress = getenv('HTTP_FORWARDED');
    else if(getenv('REMOTE_ADDR'))
        $ipaddress = getenv('REMOTE_ADDR');
    else
        $ipaddress = '114.114.114.114';
    return $ipaddress;
	}
?>

只需要将此PHP文件托管在任意服务器,使用方法为:http://HOSTNAME/geo-redirect.php?item=请求的内容

当item=flag时返回当前访客国家的国旗,否则根据访客位置到对应服务器请求相应内容。

当需要更改跳转地址时,只需要更改此PHP文件就可以,大幅提高维护效率。

效果演示:

您来自于:

Visitor_Flag

距离您最近的服务器:

Visitor_Flag

暂无评论

发表评论