Update: It looks like after receiving a 403 response, the xmlhttprequest just hangs there, and so the document.location code is never executed, any ideas on how to get around this?
I'm trying to make a bookmarklet to download videos off of YouTube, but I've come across a little problem.
To detect the highest quality video available, I use a sort of brute force method, in which I make requests using the XMLHttpRequest object until a 404 isn't returned (I can't do it until a 200 ok is returned because YouTube redirects to a different server if the video is available, and the cross-domain policy won't allow me to access any of that data).
Once a working URL is found, I simply set window.location to the URL and the download should start, right? Wrong. A request is made, but for reasons unknown to me, the cookies are stripped and YouTube returns a 403 access denied. This does not happen if the XML requests aren't made before it, i.e. if I just set window.location to the URL, everything works fine, it's when I do the XMLHttpRequest that the cookies aren't sent.
It's hard to explain so here's the script:
var formats = ["37", "22", "35", "34", "18", ""];
var url = "/get_video?video_id=" + yt.getConfig('SWF_ARGS')['video_id'] + "&t=" + (unescape(yt.getConfig('SWF_ARGS')['t'])) + "&fmt=";
for (var i = 0; i < formats.length; i++) {
xmlhttp = new XMLHttpRequest;
xmlhttp.open("HEAD", url + formats[i], false);
xmlhttp.send(null);
if (xmlhttp.status != 404) {
document.location = url + formats[i];
break
}
}
That script does not send the cookies after setting the document.location and thus does not work. However, simply doing this:
document.location = "/get_video?video_id=" + yt.getConfig('SWF_ARGS')['video_id'] + "&t=" + (unescape(yt.getConfig('SWF_ARGS')['t']))
DOES send the cookies along with the request, and does work. The only downside i开发者_如何学编程s I can't automatically detect the highest quality, I just have to try every "fmt" parameter manually until I get it right.
So my question is: why is the XMLHttpRequest object removing cookies from subsequent requests?
This is the first time I've ever done anything in JS by the way, so please, go easy on me. ;)
Update: It looks like after receiving a 403 response, the xmlhttprequest just hangs there, and so the document.location code is never executed, any ideas on how to get around this?
It seems unlikely that it's the AJAX request removing the cookie (which would be a browser bug) and more likely that YouTube is revoking the session (which is identified by the cookie) by removing the cookie. I notice the two requests are different - does this work
document.location = "/get_video?video_id=" + yt.getConfig('SWF_ARGS')['video_id'] + "&t=" + (unescape(yt.getConfig('SWF_ARGS')['t'])) + "&fmt=37"
Also try only testing for two different formats - YouTube might think you're trying to brute force, or just not allow attempted API mashups by revoking cookies from request over XMLhttp...
Drew, It is perhaps late and perhaps you know this already! But if you have access to the server's private key then you can decrypt the traffic quite easily in Wireshark. http://support.citrix.com/article/CTX116557/
精彩评论