先 logout 知乎网页。 然后浏览 http://www.zhihu.com/question/20381025。
就会看见 5 秒后将会跳转信息:

五秒过后, 跳去 www.zhihu.com/question/19694728?rf=20381025:

五秒过后, 又再跳去 www.zhihu.com/question/22447061?rf=19694728:

还没跳完,五秒过后, 又再跳去 www.zhihu.com/question/20135771?rf=22447061:

五秒过后, 跳去 www.zhihu.com/question/24531839?rf=20135771:

终于跳完 liao~ 是不是很好玩叻。当然你会觉得知乎 desgin 到酱真的是。。。
为什么我要强调 logout ? 因为 login 对知乎的重定向很大影响哦。如果没有 login, 以上所有的重定向都是交给了 js 来处理。 如果有 login,第一个重定向交给 302 处理 (所以你看不见第一页, 而是直接跳到第二页。
来证明一下,login 知乎后, 然后打开 http://www.zhihu.com/question/20381025

留意 URL bar, 是不是很奇怪叻, 直接 skip 掉 20381025 跳第二页。哦, 我还没讲上述 URL 的结构。
http://www.zhihu.com/question/问题_ID?rf=上一个重定向问题_ID
就这样, rf 猜到就是 referer 的简称。
不止这个特别,还会出现从什么问题跳转过来的信息。这就是 login 的特别之处。不但 skip 掉第一个 302, 而且会留意从哪里来。
那么如果想看回重定向之前的那页怎么办 ? 只要来得及按 "从问题 xxxxx 跳转而来" 就能看回之前那页, 并且不再重定向。这种设计,用户怎么可能懂呢 ?
login 的影响 inconsistent 的 behavior 还没完。"从问题 xxxxx 跳转而来" 本身就是 URL 加上 nr=1, 即是 no-redirect 的简称。 如果你没有 login, 你看不见 "从问题 xxxxx 跳转而来" 这行字也就算了,可是如果你手动把 URL 加上 nr=1, 比如 www.zhihu.com/question/20381025?nr=1:

还是会再跳的哦, 也就是说 login 不仅仅影响 302+js 重定向以及 block 掉 rf 信息, 而且也不允许 nr 的功能。
当然我是能想到 302+js 的初衷。302 省一次重定向, 然后又不想用户完全不懂第一页的题目, 所以只 302 静悄悄重定向一次, 接下来就用 "从问题 xxxxx 跳转而来" + js 方法重定向下一页。至于为什么要 login only 就感觉像 bug 多一点。
你可能看不懂我讲什么鬼, 简单一句, 如果是 http://www.zhihu.com/question/问题_ID?rf=上一个重定向问题_ID 链接就加上 &nr=1, 改成
http://www.zhihu.com/question/问题_ID?rf=上一个重定向问题_ID&nr=1 ,如果是 http://www.zhihu.com/question/问题_ID 链接就改成 http://www.zhihu.com/question/问题_ID?nr=1, 并且在 login 的情况下,链接是不会自动重定向的哦。
接下来让我们 DIY 两种重定向规则。
先准备 google chrome 浏览器。目标是自制 chrome extension。
准备两个 file, hello_inject.js 以及 manifest.json 放在同一个 directory/folder:

hello_inject.js 源码:
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
if (details.url && /^https?:\/\/www.zhihu.com\/question\/\d+/i.test(details.url)) {
var url = details.url;
var paramName = "nr";
var paramValue = "1";
var splitAtAnchor = url.split('#');
url = splitAtAnchor[0];
var anchor = typeof splitAtAnchor[1] === 'undefined' ? '' : '#' + splitAtAnchor[1];
if (url.indexOf(paramName + "=") >= 0) {
var prefix = url.substring(0, url.indexOf(paramName));
var suffix = url.substring(url.indexOf(paramName));
suffix = suffix.substring(suffix.indexOf("=") + 1);
suffix = (suffix.indexOf("&") >= 0) ? suffix.substring(suffix.indexOf("&")) : "";
url = prefix + paramName + "=" + paramValue + suffix;
}
else {
if (url.indexOf("?") < 0)
url += "?" + paramName + "=" + paramValue;
else
url += "&" + paramName + "=" + paramValue;
}
console.log("injected url: " + url + anchor);
return {redirectUrl: url + anchor};
}
},
{urls: ["<all_urls>"]},
["blocking"]);
manifest.json 源码:
{
"name": "URL Injector",
"version": "1.0",
"description": "Injet url.",
"background": {
"scripts": ["hello_inject.js"]
},
"manifest_version": 2,
"permissions": [ "contextMenus", "storage", "webRequest", "webRequestBlocking", "tabs", "http://*/*", "https://*/*" ]
}
然后去 chrome://extensions, 右手边打勾 Developer mode, 然后按 Load unpacked extension...:
选你刚才那个 directory/folder, 按 Open:


login 情况下,然后浏览 http://www.zhihu.com/question/20381025。

yeah, inject nr=1 成功 :)。现在每一跳问题都会自动加上 nr=1 不再跳转。当然, 必须 login 哟。
如果你不要 print log 就前面加上 // 来 comment out console.log,
//console.log("redirect url: " + url + anchor);
如果更改储存 hello_inject.js 源码文件后, 必须在 chrome://extensions/ 页面, Ctrl+r 更新 take effect。
另一种玩法是选择直接强迫它 302 redirect。原理就是依赖 login + 把 rf 丢掉。因前面研究过,我们已经懂第一页是 302, 特征就是第一页没有 rf 然后接下来有 rf。
hello_inject.js 源码:
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
if (details.url && /^https?:\/\/www.zhihu.com\/question\//i.test(details.url)) {
var url = details.url;
var base = url.substring(0, url.indexOf("?"));
var queryString = url.substring(url.indexOf("?") + 1);
var params = queryString.split("&");
var valid_param = 0;
var invalid_param = 0;
for (var i = 0; i < params.length; i++) {
var p = params[i].split("=");
if ((params[i] !== p[0]) && ( p[0] == "rf" )) {
invalid_param+=1;
} else {
if (valid_param !== 0) {
base+=params[i];
valid_param+=1;
} else {
base = base + "?" + params[i];
}
}
}
if (invalid_param !== 0) {
console.log("redirect base: " + base);
return {redirectUrl: base};
}
}
},
{urls: ["<all_urls>"]},
["blocking"]);
Ctrl+r 更新 extension, login 情况下浏览 http://www.zhihu.com/question/20381025 就会直接 skip 到最后一页 24531839:

如果 Inspect element 检测, 就能看到 302 -> 307(Internal Redirect) -> 302 -> 307 -> 302 -> 307 -> 302 -> 307 skip 到最后一页 200 OK。省下中间的 download。
































