阅读 3299

一个简单的判断用户是否在中国的方法

据说 Disqus 在中国被墙了,而我的博客又是使用 Disqus 做评论系统的,这便很难为人了。一方面我并不想去掉 Disqus,一方面 Disqus 的脚本会导致文章页面一直片于加载状态,很是尴尬。

于是便想着是否可以先探测一下当前浏览者是不是处于中国局域网,如果不是的话,再加载 Disqus 组件。无论是 <img> 还是 <iframe>,都会让浏览器显示加载状态,而 XMLHttpRequest 则不会,所以使用 XMLHttpRequest 请求一个被墙的资源就可以判断了。

首先想到的便是 Disqus 的 embed.js

var xhr = new XMLHttpRequest
xhr.open('GET', 'https://lepture.disqus.com/embed.js', true)
xhr.send()复制代码

但是这个 script 不支持跨域,console 里会显示出错警告。我们依旧可以用 xhr.readState 判断出当前 emebed.js 是否下载下来了,从而知道当前浏览器是否位于中国,可是有一个出错警告还是挺讨厌的。

后来发现还可以用 Facebook 的 API 来做测试,因为 Facebook API 有加 Access-Control-Allow-Origin:*。没有跨域问题,我们使用 graph.facebook.com/feed 作为测试接口:

function isInChina(cb) {
  var url = '//graph.facebook.com/feed?callback=h';
  var xhr = new XMLHttpRequest();
  var called = false;
  xhr.open('GET', url);
  xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
      called = true;
      cb(false);
    }
  };
  xhr.send();
  // timeout 1s, this facebook API is very fast.
  setTimeout(function() {
    if (!called) {
      xhr.abort();
      cb(true);
    }
  }, 1000);
};复制代码

gist.github.com/lepture/a9d…

注意上面加了 callback 参数,这是因为这个请求本身是有问题的,缺少 OAuth Token,如果直接请求 graph.facebook.com/feed 的话,便是 400 了。我们假装成是一个 JSONP 请求,status code 便是 200 了。

由是,我们便可知当前浏览者是否在中国局域网区,如果位于正常区域的话,便可以加载 Disqus 了。可访问我博客的中文文章页面,来看具体效果。

文章分类
前端
文章标签