本文旨在解决JavaScript在浏览器环境中跨域请求第三方网站,特别是当目标网站返回text/html类型数据时遇到的CORB(Cross-Origin Read Blocking)问题。文章将解释CORB产生的原因,并提供一种通过服务器端代理解决该问题的方案,避免直接在客户端暴露敏感信息和绕过浏览器的安全限制。
理解跨域资源共享 (CORS) 和 CORB
在Web开发中,由于浏览器的同源策略,JavaScript代码通常无法直接访问来自不同源(协议、域名或端口不同)的资源。CORS(Cross-Origin Resource Sharing)是一种机制,允许服务器声明哪些来源的网页可以访问其资源。如果服务器没有明确允许跨域访问,浏览器会阻止客户端JavaScript代码读取响应内容。
CORB(Cross-Origin Read Blocking)是浏览器的一种安全机制,用于阻止跨域读取某些类型的响应,例如text/html,以防止潜在的安全漏洞,例如跨站脚本包含(XSSI)攻击。 当浏览器检测到跨域请求返回text/html内容时,并且服务器没有设置适当的CORS头,CORB就会阻止JavaScript访问响应体。
问题分析:为何直接使用JavaScript请求失败?
直接在JavaScript中使用$.ajax或其他方式请求https://pubmed.ncbi.nlm.nih.gov/?term=hello这类返回text/html的URL,并且没有正确配置CORS的服务器,会导致以下问题:
立即学习“Java免费学习笔记(深入)”;
- Access-Control-Allow-Origin缺失: 目标服务器没有设置Access-Control-Allow-Origin头,或者设置的值不允许当前域访问。
- CORB阻止: 即使请求成功(状态码200),浏览器也会阻止JavaScript读取响应内容,因为CORB认为text/html内容可能包含敏感信息,直接暴露给跨域脚本存在安全风险。
- dataType: “jsonp” 的误用: JSONP 是一种古老的跨域技术,它依赖于动态创建 <script> 标签,并且要求服务器返回特定格式的 JSON 数据,包裹在一个回调函数中。 pubmed.ncbi.nlm.nih.gov 显然不是为 JSONP 设计的,所以使用 dataType: “jsonp” 不会解决问题,反而可能引入更多问题。
解决方案:使用服务器端代理
解决此类跨域问题的最佳实践是使用服务器端代理。这意味着你的JavaScript代码向你的服务器发送请求,然后你的服务器再代表客户端向目标服务器发送请求,并将响应转发回客户端。 这样可以绕过浏览器的同源策略,因为所有的跨域请求都发生在服务器端。
步骤如下:
-
客户端 (JavaScript):
function fetchData() { fetch('/api/pubmed?term=hello') // 你的服务器端代理地址 .then(response => { if (!response.ok) { throw new Error('Network response was not ok ' + response.status); } return response.text(); // 获取文本数据 }) .then(data => { console.log(data); // 处理从服务器返回的数据 }) .catch(error => { console.error('There has been a problem with your fetch operation:', error); }); } fetchData();
-
服务器端 (Node.js 示例):
const express = require('express'); const axios = require('axios'); const cors = require('cors'); // 引入 cors 中间件 const app = express(); const port = 3000; app.use(cors()); // 启用 CORS app.get('/api/pubmed', async (req, res) => { const searchTerm = req.query.term; const targetUrl = `https://pubmed.ncbi.nlm.nih.gov/?term=${searchTerm}`; try { const response = await axios.get(targetUrl); res.send(response.data); // 将目标网站的响应返回给客户端 } catch (error) { console.error(error); res.status(500).send('Internal Server Error'); } }); app.listen(port, () => { console.log(`Server listening at http://localhost:${port}`); });
代码解释:
- express 是一个流行的 Node.js Web 框架,用于创建服务器。
- axios 是一个基于 Promise 的 HTTP 客户端,用于发送 HTTP 请求。
- cors 是一个用于处理 CORS 问题的中间件。 app.use(cors()); 允许来自所有域的请求。 在生产环境中,你应该配置 cors 以仅允许来自你的客户端域的请求。
- /api/pubmed 是服务器端代理的路由。
- 服务器接收客户端的请求,构造目标 URL,使用 axios 发送 GET 请求,并将目标网站的响应数据直接返回给客户端。
- 错误处理:如果请求失败,服务器会返回 500 错误。
注意事项:
- 安全性: 在生产环境中,请确保对代理请求进行适当的身份验证和授权,以防止未经授权的访问。
- CORS配置: 如果你的服务器和客户端部署在不同的域上,你需要配置服务器的 CORS 头,允许你的客户端域访问。 使用 cors 中间件可以简化此过程。
- 错误处理: 在服务器端添加适当的错误处理,以处理请求失败的情况。
- 数据处理: 根据实际需求,在服务器端对响应数据进行处理,例如提取所需的信息,转换数据格式等。
- 性能: 如果代理的流量很大,可以考虑使用缓存来提高性能。
总结
直接在客户端JavaScript中跨域请求text/html类型的资源通常会受到浏览器的安全限制。 使用服务器端代理是一种安全且可靠的解决方案。 通过在服务器端发送请求并将响应转发回客户端,可以绕过浏览器的同源策略和CORB限制。 在实际应用中,请务必注意安全性、CORS配置、错误处理和性能优化。
以上就是解决跨域请求text/javascript java html js node.js json ajax node go 浏览器 app JavaScript 中间件 json ajax html express Resource 回调函数 JS promise http https 性能优化 Access axios