为什么某些“ file://”提取调用被允许,而另一些则被“跨原始请求阻止”?

时间:2019-03-27 17:21:29

标签: javascript

我刚开始学习javascript,所以请多多包涵。

我有两个html页面,例如page1.html和page2.html。两个页面上都有两个按钮,“下一个”和“上一个”。想法是打开序列中的下一页或上一页。我通过将window.location.href设置为新的file://网址来打开新页面。当然,除了尝试访问页面 0 或页面 3 时,浏览器会显示找不到文件。

因此,我决定尝试使用fetch并仅在response.oktrue的情况下打开新页面。这是我处理button.onclick的函数:

fetch(url).then(function(response) {
    if (response.ok) {
        window.location.href = url;
    }
    else {
        alert("This is the last page.");
    }
});

当页面存在(它打开页面)时,它按预期工作。但是,如果不这样做,控制台将显示1条警告和1条错误(并且根本不会更改页面,也不会触发alert):

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at file:///path/to/page3.html. (Reason: CORS request not http).
TypeError: NetworkError when attempting to fetch resource.

我四处搜索,发现非http请求出于安全原因被阻止(不允许网页随心所欲地访问本地文件)。

让我感到困惑的是,即使文件存在(第1页或第2页),它仍然是非HTTP请求,但仍然有效。为什么仅在文件不存在时才阻止它?我为什么要在它旁边放一个NetworkError

1 个答案:

答案 0 :(得分:2)

fetch(无论如何在浏览器中)具有this to say个有关file:网址:

  

就目前而言,不幸的是,文件URL留给读者练习。

     

如有疑问,请返回网络错误。

通常,fetch不会以file: URL成功。可悲的是,似乎在Firefox上,如果要提取的文件存在,则成功,但是如果不存在,则抛出网络错误。 (我想这是有道理的,它并不是可以返回HTTP状态代码;它不是使用HTTP。)在Chrome和Edge上,无论文件是否存在,它总是会失败。在某些浏览器(例如Chrome)中,较旧的XMLHttpRequest也没有(但是在其他浏览器(例如Firefox)中,它确实存在)。

fetch / XMLHttpRequest与设置页面的href之间的主要区别在于,在前一种情况下,页面A上的代码能够读取页面B的内容;但在后一种情况下,它无法-它可以进入页面B,但是无法读取页面B的内容。页面A替换为页面B。

如果XMLHttpRequest已在我们现在居住的安全环境中进行了标准化,我怀疑它也将明确禁止访问file: URL。


由于Firefox将不存在的文件视为NetworkError,因此您的代码(仅适用于Firefox)可能是:

// With file: URLs, this ONLY works in Firefox
fetch(url)
.then(function(response) {
    if (!response.ok) {
        throw new Error("HTTP status " + response.status);
    }
})
.then(function() {
    window.location.href = url;
})
.catch(error => {
    alert("This is the last page.");
});

或者也许:

fetch(url)
.then(function(response) {
    return response.ok;
})
.catch(function() {
    return false;
})
.then(function(flag) {
    if (flag) {
        window.location.href = url;
    } else {
        alert("This is the last page.");
    }
});

您可以在此处使用箭头功能。我不是因为你没有,而是:

fetch(url)
.then(response => response.ok)
.catch(() => false)
.then(flag => {
    if (flag) {
        window.location.href = url;
    } else {
        alert("This is the last page.");
    }
});