Clash Royale CLAN TAG#URR8PPP
Switching between Youku and YouTube based on whether you're in China
I'm hosting a conference website where I want to embed a Youku video if you're in China and a YouTube video otherwise. The conference website is being served through a CDN inside the Great Firewall. I was given the code below to switch between internal and external versions of Youku.
Unfortunately, ipinfo.io does not seem to be accessible inside the Great Firewall, so the code times out after 10 seconds.
I've considered rewriting the page to use a Youku video by default, writing a small, non-blocking JavaScript function that tries to reach YouTube. If it can, replace the Youku with YouTube. If it can't, exit harmlessly. That way, the reachability of YouTube becomes the key test, not whether you're in China.
Alternatively, I've thought of hosting the video on my site, so that it will be replicated via the CDN inside the Great Firewall. However, that would mean that the video would always be downloaded at full resolution, even if you're on a slow connection.
Any better suggestions on how to switch between Youku and Youtube, or more generally have a video playable both inside and outside China?
jQuery.get("https://ipinfo.io", function(response) {
var country = response.country;
if(country == 'CN') {
youku.attr('src',chinaVideo)
} else {
youku.attr('src',generalVideo)
}
}, "jsonp");
This question has not received enough attention.
I'd love to hear from anyone with actual experience dealing with Great Firewall issues.
5 Answers
5
Here's the JavaScript we're going with:
<script type="text/javascript">
var country = '',
youku = jQuery('#youku');
jQuery.get("https://ipinfo.io", function(response) {
var country = response.country;
if(country != 'CN') {
youku.attr('src','https://www.youtube.com/embed/K3cEE5h7c1s')
}
}, "jsonp");
We're including the Youku link in the HTML and switching to YouTube if country is not China. This still works if connecting to ipinfo.io times out, which sometimes happens in China.
Your current solution is not ideal as it depends on the GET request timing out, which is going to slow things down. Since the issue largely revolves around ipinfo.io
being blocked in China, it's likely that an effective solution would involve an IP identification service based within China.
ipinfo.io
Try using http://www.ip138.com/
. Google Translate works well enough to read it in English. There doesn't seem to be a formal JSON API, but you can hit http://www.ip138.com/ips138.asp?ip=<IP_ADDRESS_HERE>
and get the location info.
http://www.ip138.com/
http://www.ip138.com/ips138.asp?ip=<IP_ADDRESS_HERE>
To do so, navigate the DOM with jQuery (since you're already using it) to the line with 本站数据:
, which will precede the name of the country. I think the selector for that as the page is currently constructed is simply $( "li" ).first()
. Extract the string after the colon and the POST it to the Google Translate API to get the country name in English and voila! You have a faster and more reliable (if considerably more complicated) way to see if a visitor is in China or not.
本站数据:
$( "li" ).first()
EDIT: It is not entirely clear if you possess the user's IP address beforehand. If not, you can use a similar method with https://geoiptool.com/zh/
, which is also based within China and thus not blocked. I'm happy to flesh this part out as needed.
https://geoiptool.com/zh/
It is better to specifically check if YouTube is blocked in user's network rather than filtering out country based on IP which is never 100% reliable. This way it will even work in any school/office environment where YouTube could be blocked by network administrator for any reason.
This is the best answer I could find in this regard which tries to load the favicon
of YouTube via JavaScript. If it succeeds to download that tiny image, YouTube is accessible. The image is only 0.2 kilobytes of download and it is most likely already cached by any user who ever visited YouTube.
favicon
That means the result is almost instantaneous for users with YouTube access and will take few seconds for users with blocked firewalls. The code is simple:
jQuery(function(){
var youku = jQuery('#youku');
var image = new Image();
image.onload = function(){
youku.attr('src','https://www.youtube.com/embed/K3cEE5h7c1s')
};
image.onerror = function(){
youku.attr('src','https://www.youku.com/embed/K3cEE5h7c1s')
};
image.src = "https://youtube.com/favicon.ico";
});
This one is a better solution than stated above as it does not wait for document.ready
event of jQuery, the image starts to load instantly.
document.ready
(function(){
var image = new Image();
image.onload = function(){
jQuery(function(){
jQuery('#youku').attr('src','https://www.youtube.com/embed/K3cEE5h7c1s')
});
};
image.onerror = function(){
jQuery(function(){
jQuery('#youku').attr('src','https://www.youku.com/embed/K3cEE5h7c1s')
});
};
image.src = "https://youtube.com/favicon.ico";
})();
Any better suggestions on how to switch between Youku and Youtube, or
more generally have a video playable both inside and outside China?
I'd suggest taking a look at Alibaba Cloud. They have a bunch of services, but AFAIK there is no free plan.
Since I'm not familiar with other cloud providers for China, let me describe a solution for Alibaba Cloud.
I see two possible options for you:
What about using the client's time zone? While not perfect, it would allow you to avoid relying on timeouts or any geoip service requests altogether.
console.log(Intl.DateTimeFormat().resolvedOptions().timeZone)
This is reasonably well-supported in modern browsers. In China, it should return the IANA time zone for China: "Asia/Shanghai".
There are also libraries (jsTimezoneDetect and moment-timezone) that combine the above along with the getTimezoneOffset
function of Date
across multiple points in time, to make an educated guess of time zone, which may yield better results with older browsers:
getTimezoneOffset
Date
console.log(jstz.determine().name());
console.log(moment.tz.guess());
<script src="//cdnjs.cloudflare.com/ajax/libs/jstimezonedetect/1.0.6/jstz.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.5/moment-timezone-with-data-2010-2020.min.js"></script>
For my part, I'd probably try detecting the time zone as "Asia/Shanghai" and fallback to a time zone offset of "UTC+8" (time zone offset alone will catch more than mainland China but I would imagine that's an acceptable overreach for a fallback strategy), e.g.:
var ianaTz = Intl.DateTimeFormat().resolvedOptions().timeZone;
var offset = new Date().getTimezoneOffset();
if (ianaTz === "Asia/Shanghai" || (ianaTz == null && offset/60 == -8)) {
console.log("We'll assume China");
} else {
console.log("not China");
}
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
By keeping a common code base for all, you can make a separate cartridge for china, and write the youku code for your video in that cartridge, whenever user hits the URL, if the URL contains the id for the Chinese locale, then that code can override the default code.
– Code_Ninja
2 days ago