浏览器HTTP缓存规则导致的跨域

浏览器HTTP缓存规则导致的跨域

现象

  • 两个域名
    • localhost:5500(下面简称5500)
    • localhost:5501(下面简称5501)
  • 后台跨域:正确的配置了5500和5501允许跨域访问
  • 当再5500中缓存一个跨域请求后,打开5501后请求相同的请求,结果在5501中出现跨域

⚠️ 在5501中的跨域错误显示的是Access-Control-Allow-Origin: http://localhost:5500 (???? WTF ???)

  • 猜想:浏览器的缓存是基于主域名
ts 复制代码
localhost // 子域名命中: a.localhost,b.localhost...; 不同端口命中: localhost:5500, localhost: 5501...
	- test跨域请求

baidu.com // 不同域名互不干扰
	- ...

源码

  1. page1.html
html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Page1</title>
</head>

<body>
  <h1>this is page1.html</h1>
  <button onclick="window.open('http://localhost:5501/page2.html')">打开page2</button>
</body>
<script type="module">
  const res = await fetch("http://127.0.0.1:3000");
  const json = await res.json();
  const div = document.createElement("div");
  div.innerText = json.message;
  document.body.appendChild(div);
</script>

</html>
  1. page2.html
html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Page2</title>
</head>

<body>
  <h1>this is page2.html</h1>
</body>
<script type="module">
  const res = await fetch("http://127.0.0.1:3000");
  const json = await res.json();
  const div = document.createElement("div");
  div.innerText = json.message;
  document.body.appendChild(div);
</script>

</html>
  1. nodejs后台 (我的环境是node v20+)
ts 复制代码
const { log } = require("console");
const http = require("http");

const server = http.createServer((req, res) => {
  const origin = req.headers.origin;

  log("origin", req.headers.origin);
  res.writeHead(200, {
    "Content-Type": "application/json; charset=utf-8",
    "Access-Control-Allow-Origin": origin,
    "Cache-Control": "private, max-age=60", // 强制缓存60s
  });
  res.end(JSON.stringify({ message: "Hello, World!" }));
});

server.listen(3000, () => {
  console.log("Server running on http://127.0.0.1:3000");
});

验证

  1. localhost:5500是page1.html
  2. localhost:5501是page2.html
  3. 先在5500中访问,一切正常
  1. 点击"打开page2"访问localhost:5501的page2.html,不出意外的话,打开控制台就会出现CORS错误

当强制刷新5501的page2.html后,会正常显示

解决方案

  1. 请求后拼接上随机数(适合应急上线,治标不治本)
ts 复制代码
fetch(`http://127.0.0.1:3000/?random=${Math.random()}`)
  1. 对于静态资源加上缓存完全没问题,如果是业务请求或者是业务相关的资源,个人觉得最好不要加上响应头去缓存。如果有缓存业务,可以采用JS代码去缓存
    • localForage库(本地缓存在localStorage、IndexedDB...)
    • MDN Caches 浏览器提供的缓存相关的接口
  2. 后台配置 Vary: Origin(未经过测试,理论上协商缓存可行,强缓存不行)

💡 查阅了MDN、stackoverflow、chromeium issue、WHATWG 都没有相关的介绍,如果有明确的来源欢迎评论👏

相关推荐
UXbot1 小时前
UI设计工具推荐合集
前端·人工智能·ui
敲敲了个代码2 小时前
如何优化批量图片上传?队列机制+分片处理+断点续传三连击!(附源码)
前端·javascript·学习·职场和发展·node.js
@AfeiyuO2 小时前
Vue 引入全局样式scss
前端·vue·scss
光影少年2 小时前
flex布局和grid布局区别,实现两边固定布局中间自适应
前端·css3·web·ai编程
全栈测试笔记2 小时前
异步函数与异步生成器
linux·服务器·前端·数据库·python
EndingCoder3 小时前
配置 tsconfig.json:高级选项
linux·前端·ubuntu·typescript·json
木风小助理3 小时前
JavaStreamAPI的性能审视,优雅语法背后的隐形成本与优化实践
java·前端·数据库
Tandy12356_3 小时前
手写TCP/IP协议栈——HTTP协议实现(完结篇)
c语言·网络·网络协议·tcp/ip·计算机网络·http
yangSnowy3 小时前
webSocket 通信详解
网络·websocket·网络协议
white-persist4 小时前
轻松抓包微信小程序:Proxifier+Burp Suite教程
前端·网络·安全·网络安全·微信小程序·小程序·notepad++