持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第31天,点击查看活动详情
1、cors
直接在服务端做手脚
- node直接显示页面
...
<body>
HELLO
</body>
// server1.js
const express = require("express")
const app = express()
app.use(express.static(__dirname)) // 以当前目录作为静态文件目录
app.listen(3000)
启动服务后,访问 localhost:3000/index.html ,即可看到页面 HELLO
为了实现跨域,我们再启动一个 4000 端口的服务
// server2.js
const express = require("express")
const app = express()
app.get("/getData", function(req,res) {
res.end("我是4000的getData")
})
app.use(express.static(__dirname)) // 以当前目录作为静态文件目录
app.listen(4000)
- 修改
index.html
<body>
<script>
let xhr = new XMLHttpRequest()
xhr.open("GET", "http://localhost:4000/getData", true)
xhr.withCredentials = true; // 强制携带凭证:cookie默认是不允许跨域的,加上这段代码,就可以让跨域请求强制加上cookie
xhr.setRequestHeader("name", "hayes") // 设置请求头(服务器也需要相应的允许设置)
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
console.log(xhr.response);
}
}
}
xhr.send()
</script>
</body>
此时两个服务都启动起来,再访问 localhost:3000/index.html,会发现跨域了。
在 server2 中添加一行打印,来观察一下请求头
app.get("/getData", function(req,res) {
console.log(req.headers); // 观察请求头
res.end("我是4000的getData")
})
- 有请求头打印,说明请求发过来了
- 可以看到请求源是
localhost:3000端口的
修改server2
const express = require("express")
const app = express()
const whiteList = ["http://localhost:3000"] // 允许跨域的白名单
app.use(function(req, res, next) {
let origin = req.headers.origin; // 取出请求源
if(whiteList.includes(origin)) {
res.setHeader("Access-Control-Allow-Origin", origin) // 设置哪个源可以访问我
res.setHeader("Access-Control-Allow-Headers", "name") // 允许的请求头
res.setHeader("Access-Control-Allow-Methods", "PUT") // 允许PUT请求
res.setHeader("Access.Control-Allow-Credentials", true) // 允许携带cookie
res.setHeader("Access-Control-Max-Age", 6) // 预检存活时间:6秒内不会再次发送预检请求
if(res.method === "OPTIONS") { // 预检请求不是每次都发
res.end() // 预检请求不做任何处理
}
}
next()
})
app.get("/getData", function(req,res) {
console.log(req.headers);
res.end("我是4000的getData")
})
app.use(express.static(__dirname))
app.listen(4000)
此时再访问,就可以看到控制台打印的结果了:我是4000的getData
2、postMessage
两个页面之间通信
- 页面a
<body>
a
</body>
- 页面b
<body>
b
</body>
- 服务a
const express = require("express")
const app = express()
app.use(express.static(__dirname)) // 以当前目录作为静态文件目录
app.listen(3000)
- 服务b
const express = require("express")
const app = express()
app.use(express.static(__dirname)) // 以当前目录作为静态文件目录
app.listen(4000)
- 现在我们想把 b 页面 嵌入 a 页面
// 页面a
<body>
<iframe src="http://localhost:4000/b.html" frameborder="0" id="iframe" onload="load()"></iframe>
<script>
function load() {
// 在加载完成(load)后,拿到b的iframe,像页面b(4000端口)发消息
let iframe = document.getElementById("iframe");
iframe.contentWindow.postMessage("你好呀", "http://localhost:4000")
}
</script>
</body>
- 页面b接收消息
<body>
<script>
window.onmessage = function(e) {
console.log(e.data); // 打印消息
}
</script>
</body>
打开页面 a,可以看到页面 b 打印的消息
- 接下来我们让页面
b回发消息给“消息源”(也就是页面a)
<body>
<script>
window.onmessage = function(e) {
console.log(e.data);
e.source.postMessage("我不好", e.origin) // 回发消息至哪个源
}
</script>
</body>
- 页面a接收回发(postMessage)的消息
<body>
<iframe src="http://localhost:4000/b.html" frameborder="0" id="iframe" onload="load()"></iframe>
<script>
function load() {
let iframe = document.getElementById("iframe");
iframe.contentWindow.postMessage("你好呀", "http://localhost:4000")
// 接收自己的window的消息
window.onmessage = function(e) {
console.log(e.data);
}
}
</script>
</body>
现在访问 http://localhost:3000/a.html就可以看到两条打印出的消息了
页面a 中嵌入页面b => a向b发送消息 => b接收到消息后,回发给a另外一条消息 => 页面a接收到b回发的消息