PDF.js CORS 问题

28,060次阅读
没有评论

共计 3988 个字符,预计需要花费 10 分钟才能阅读完成。

问题概要

我从域 A 将 PDF.js 加载到 iframe 中,并以文件作为参数(服务器的完整路径,这将返回 pdf 文档)。PDF.js 将向域 B 的服务器创建一个请求,扩展名为 origin: domain A. 域 B 的服务器返回带有 header 的 pdf 文档 Access-Control-Allow-Origin: domain A,到目前为止一切顺利。

在我的网络选项卡中,我看到对服务器的请求,该请求返回 200 状态 OK,但 PDF.js 抛出错误 Unexpected server response (0) while retrieving PDF

问题是,这里发生了什么,CORS 似乎没问题,但我无法从 PDF.js 获得更多信息,真正的原因是 PDF 无法加载。有没有人遇到过同样的情况?

问题解决

跨域 Ajax 与跨源资源共享

几年前,Web 开发人员正在用头撞 Ajax 的第一堵墙:同源策略。虽然我们惊叹于跨浏览器支持所带来的巨大进步 XMLHttpRequest 对象,我们很快就抱怨没有办法从 JavaScript 向不同的域发出请求。每个人都在自己的网站上设置代理,这是一系列新的开放重定向问题的开始,作为绕过限制的一种方法。尽管开发人员正在使用服务器端代理以及其他技术来解决此限制,但社区对允许本机跨域 Ajax 请求的强烈抗议。许多人没有意识到,几乎所有浏览器(Internet Explorer 8+、Firefox 3.5+、Safari 4+ 和 Chrome)目前都通过称为跨源资源共享的协议支持跨域 Ajax。

跨域资源共享 (CORS)

跨源资源共享 (CORS) 是 W3C 工作草案,定义了跨源访问源时浏览器和服务器必须如何通信。CORS 背后的基本思想是使用自定义 HTTP 标头,让浏览器和服务器充分了解彼此,以确定请求或响应应该成功还是失败。

对于一个简单的请求,即使用 GET 或 POST 且不带自定义标头且正文为 的请求 text/plain,该请求会使用名为 的额外标头发送 Origin。标 Origin 头包含请求页面的来源(协议、域名和端口),以便服务器可以轻松确定是否应该提供响应。示例 Origin 标头可能如下所示:

Origin: https://humanwhocodes.com

如果服务器决定允许该请求,它会发送一个 Access-Control-Allow-Origin 标头,回显与发送的相同来源或“*”(如果它是公共资源)。例如:

Access-Control-Allow-Origin: https://humanwhocodes.com

如果此标头丢失,或者来源不匹配,则浏览器将不允许该请求。如果一切顺利,浏览器就会处理该请求。请注意,请求和响应都不包含 cookie 信息。

前面提到的所有浏览器都支持这些简单的请求。Firefox 3.5+、Safari 4+ 和 Chrome 都支持通过该 XMLHttpRequest 对象使用。当尝试打开不同来源的资源时,此行为会自动触发,无需任何额外代码。例如:

var xhr = new XMLHttpRequest();
xhr.open("get", "https://humanwhocodes.com/some_resource/", true);
xhr.onload = function(){//instead of onreadystatechange
//do something
};
xhr.send(null);

要在 Internet Explorer 8 中执行相同的操作,您需要以相同的方式使用该 XDomainRequest 对象:

var xdr = new XDomainRequest();
xdr.open("get", " 
xdr.onload = function(){//do something};
xdr.send();

Mozilla 团队在有关 CORS 的帖子中建议您应该检查该 withCredentials 属性是否存在,以确定浏览器是否通过 XHR 支持 CORS。然后,您可以结合该 XDomainRequest 对象的存在来覆盖所有浏览器:

function createCORSRequest(method, url){var xhr = new XMLHttpRequest();
    if ("withCredentials" in xhr){xhr.open(method, url, true);
    } else if (typeof XDomainRequest != "undefined"){xhr = new XDomainRequest();
        xhr.open(method, url);
    } else {xhr = null;}
    return xhr;
}

var request = createCORSRequest("get", "https://humanwhocodes.com/");
if (request){request.onload = function(){//do something with request.responseText};
    request.send();}

Firefox、Safari 和 Chrome 中的对象 XMLHttpRequest 与 IE 对象具有足够相似的接口 XDomainRequest,因此该模式工作得相当好。常见的接口属性 / 方法有:

  • abort()– 用于停止已经在进行的请求。

  • onerror– 使用而不是 onreadystatechange 检测错误。

  • onload– 使用而不是 onreadystatechange 检测成功。

  • responseText– 用于获取响应内容。

  • send()– 用于发送请求。

预检请求

CORS 允许通过称为预检请求的透明服务器验证机制使用自定义标头、GET 或 POST 以外的方法以及不同的正文内容类型。当您尝试使用高级选项之一发出请求时,系统会向服务器发出“预检”请求。此请求使用 OPTIONS 方法并发送以下标头:

  • Origin– 与简单请求相同。

  • Access-Control-Request-Method– 请求想要使用的方法。

  • Access-Control-Request-Headers–(可选)正在使用的自定义标头的逗号分隔列表。

假设一个带有名为 的自定义标头的 POST 请求的示例 NCZ:

Origin: https://humanwhocodes.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: NCZ

文章来源地址 https://www.toymoban.com/diary/js/293.html

在此请求期间,服务器可以确定是否允许此类请求。服务器通过在响应中发送以下标头将此信息传达给浏览器:

  • Access-Control-Allow-Origin– 与简单请求相同。

  • Access-Control-Allow-Methods– 允许的方法的逗号分隔列表。

  • Access-Control-Allow-Headers– 服务器允许的标头的逗号分隔列表。

  • Access-Control-Max-Age– 此预检请求应缓存的时间(以秒为单位)。

例子:

Access-Control-Allow-Origin: https://humanwhocodes.com
Access-Control-Allow-Methods: POST, GET
Access-Control-Allow-Headers: NCZ
Access-Control-Max-Age: 1728000

一旦发出预检请求,结果将被缓存响应中指定的时间段;您只会在第一次发出此类请求时产生额外 HTTP 请求的费用。

Firefox 3.5+、Safari 4+ 和 Chrome 均支持预检请求;Internet Explorer 8 没有。

凭证请求

默认情况下,跨源请求不提供凭据(cookie、HTTP 身份验证和客户端 SSL 证书)。您可以通过将该属性设置为 true 来指定请求应发送凭据 withCredentials。如果服务器允许凭据请求,则它会使用以下 HTTP 标头进行响应:

Access-Control-Allow-Credentials: true

如果发送了凭据请求并且此标头未作为响应的一部分发送,则浏览器不会将响应传递给 JavaScript(responseText 是空字符串,status 为 0,并且 onerror() 被调用)。请注意,服务器还可以发送此 HTTP 标头作为预检响应的一部分,以指示允许源发送凭证请求。

Internet Explorer 8 不支持该 withCredentials 属性;Firefox 3.5、Safari 4 和 Chrome 都支持它。

结论

现代 Web 浏览器对跨域 Ajax 提供了大量可靠的支持,但大多数开发人员仍然没有意识到这种强大的功能。使用时只需要一点额外的 JavaScript 工作和一点额外的服务器端工作即可确保发送正确的标头。IE8 的实现在允许高级请求和凭据请求方面落后于其他版本,但希望对 CORS 的支持将继续改进。

到此这篇关于 PDF.js CORS 问题的文章就介绍到这了, 更多相关内容可以在右上角搜索或继续浏览下面的相关文章,希望大家以后多多支持 TOY 模板网!

原文地址:https://www.toymoban.com/diary/js/293.html

如若转载,请注明出处:如若内容造成侵权 / 违法违规 / 事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

    正文完
     0
    Yojack
    版权声明:本篇文章由 Yojack 于1970-01-01发表,共计3988字。
    转载说明:
    1 本网站名称:优杰开发笔记
    2 本站永久网址:https://yojack.cn
    3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
    4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
    5 本站所有内容均可转载及分享, 但请注明出处
    6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
    7 站长邮箱:laylwenl@gmail.com
    评论(没有评论)