使用JavaScript fetch请求时遇到异常问题求助
Naurok API 请求差异问题分析与解决
现象梳理
- 带斜杠的URL
https://naurok.com.ua/api2/test/sessions/303532970/:- 直接请求会触发重定向,目标为
http://naurok.com.ua/api2/test/sessions/303532970(无HTTPS和斜杠),普通浏览器模式下会因混合内容被拦截 - Firefox开启HTTPS-only模式时,会自动把重定向的HTTP请求升级为HTTPS,此时请求成功返回完整数据:
Object { session: {…}, settings: {…}, document: {…}, questions: (10) […] }
- 直接请求会触发重定向,目标为
- 不带斜杠的URL
https://naurok.com.ua/api2/test/sessions/303532970:- 浏览器直接打开可正常加载,无重定向,返回预期数据
- 用
fetch请求时,请求流程无异常,但API返回"false"——哪怕复制浏览器的请求头、用DevTools生成的fetch代码也无法解决
浏览器直接请求与fetch请求的核心差异
1. 请求上下文校验
浏览器直接打开URL属于顶级导航请求,而fetch是脚本发起的请求。服务器可能会通过以下头信息区分请求来源:
Sec-Fetch-*系列头:比如Sec-Fetch-Mode: navigate(浏览器导航)和Sec-Fetch-Mode: cors(脚本请求),服务器可能只信任导航模式的请求Referer/Origin:脚本请求的Referer可能为空或与当前页面域名相关,而浏览器导航的Referer可能符合服务器的校验规则
2. Cookie传递逻辑
- 浏览器导航会自动携带该域名下的所有Cookie(包括HttpOnly类型)
fetch默认仅在同源请求中携带Cookie,若用户脚本运行在其他域名下,必须显式设置credentials: 'include'才能跨域传Cookie;即使同源,部分服务器会校验Cookie的SameSite属性,脚本请求可能不满足要求
3. 重定向处理规则
- 浏览器导航会自动跟随重定向,HTTPS-only模式还会强制把HTTP重定向升级为HTTPS
fetch默认跟随重定向,但重定向到HTTP时会被混合内容策略拦截,无法自动升级协议
针对性解决办法
方案1:手动处理带斜杠URL的重定向
拦截重定向请求,自行将HTTP地址替换为HTTPS:
fetch("https://naurok.com.ua/api2/test/sessions/303532970/", { redirect: 'manual' }) .then(response => { if ([301, 302].includes(response.status)) { const redirectUrl = response.headers.get('Location').replace('http://', 'https://'); return fetch(redirectUrl, { credentials: 'include' }); } return response; }) .then(res => res.json()) .then(console.log) .catch(err => console.error(err));
方案2:模拟浏览器导航的请求头
复制浏览器直接请求时的完整请求头(包括Sec-Fetch-*系列),并强制携带Cookie:
fetch("https://naurok.com.ua/api2/test/sessions/303532970", { method: 'GET', headers: { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/115.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8', 'Accept-Language': 'en-US,en;q=0.5', 'Connection': 'keep-alive', 'Upgrade-Insecure-Requests': '1', 'Sec-Fetch-Dest': 'document', 'Sec-Fetch-Mode': 'navigate', 'Sec-Fetch-Site': 'none', 'Sec-Fetch-User': '?1' }, credentials: 'include' }) .then(res => res.json()) .then(console.log) .catch(err => console.error(err));
方案3:用用户脚本专用请求API
在Tampermonkey/Greasemonkey等环境中,使用GM_xmlhttpRequest可以绕过部分浏览器限制,更贴近原生请求行为:
GM_xmlhttpRequest({ method: "GET", url: "https://naurok.com.ua/api2/test/sessions/303532970", onload: function(response) { console.log(JSON.parse(response.responseText)); }, onerror: function(err) { console.error(err); } });
内容的提问来源于stack exchange,提问作者griffi-gh
相关产品推荐
相关产品推荐

