媒介
常言道,”讀萬卷書,不如行萬里路”。手藝的進修也是云云,惟有實踐才更清晰的邃曉道理和加深印象,因而本文會應用node.js對前端的種種跨域體式格局舉行實踐,強烈建議一步一步隨着做,相信你一定會對跨域有更深條理的明白。而由於篇幅限定,本文只會貼出關鍵性的代碼,本系列統共分為上下篇。詳細的代碼請移步我的Github。假如對你有協助的話,迎接 star ヾ(´・ω・`)ノ
接上文—>「跨域」應用node.js實踐前端種種跨域體式格局(上)
六、window.postMessage
postMessage是HTML5 XMLHttpRequest Level 2中的API,且是為數不多能夠跨域操縱的window屬性之一,它可用於處置懲罰以下方面的題目:
1.頁面和其翻開的新窗口的數據通報
2.多窗口之間音訊通報
3.頁面與嵌套的iframe音訊通報
4.上面三個場景的跨域數據通報
用法:postMessage(data,origin)
要領吸收兩個參數
data: html5範例支撐恣意基礎範例或可複製的對象,但部份瀏覽器只支撐字符串,所以傳參時最好用JSON.stringify()序列化。
origin: 協定+主機+端口號,也能夠設置為”*”,示意能夠通報給恣意窗口,假如要指定和當前窗口同源的話設置為”/”。
來,我們來用node.js實踐一下~
目次:postMessage/public/a.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>a</title>
<iframe id="iframe" src="http://localhost:4444/b.html" style="display:none;"></iframe>
</head>
<body>
<script>
const iframe = document.getElementById('iframe');
iframe.onload = function() {
const data = {
name : 'Jchermy'
};
//向http://localhost:4444 發送跨域數據
iframe.contentWindow.postMessage(JSON.stringify(data), "http://localhost:4444");
};
//吸收 localhost:4444 返回的數據
window.addEventListener('message', function(e){
alert('data from b.html ----->' + e.data);
},false);
</script>
</body>
</html>
在iframe加載完成后,向b.html地點域發送數據。由於postMessage是綁定在window對象上的,所以我們要獵取iframe.contentWindow再發送數據,同時監聽message
,視察b.html有無回傳數據給我們。如今分別跑兩個效勞。接見localhost:3333能夠看到:
b.html吸收到a.html發送過去的數據啦~
然後a.html也收到了b.html回傳的數據了。
跨域勝利~ ( 。ớ ₃ờ)ھ
七、nginx 反向代辦
這個計劃的道理圖以下:
申明:當A域想與B域通信,能夠經由過程nginx的反向代辦,起首A域與同域的nginx效勞器通信,然後nginx將要求轉發到別的一個效勞器,由於效勞器之間的通信不存在跨域,如許我們就完成了跨域。詳細完成以下:
起首,假如當地沒有裝置nginx的,須要裝置nginx。裝置完成后,我們對nginx舉行設置:
目次:nginx-1.14.0/conf/nginx.conf
server {
listen 1111;
server_name localhost;
location / {
proxy_pass http://localhost:9999/; #反向代辦到9999端口
index index.html index.htm;
default_type "text/html";
alias "D:/Github/node-server/nginx/public/"; #client.html地點的當地的地點
add_header Access_Control_Allow_Origin http://localhost:1111;
add_header Access_Control_Allow_Credentials true; #許可客戶端帶cookie接見
}
然後,我們設置9999端口的效勞器
目次:nginx/server.js
const http = require('http');
const server = http.createServer();
const qs = require('querystring');
server.on('request', function(req, res) {
const query = require('url').parse(req.url, true).query;
//向前台寫cookie
res.writeHead(200, {
'Set-Cookie' : 'name=jchermy;Path:/;Domain:localhost;Httponly' //HttpOnly 劇本沒法讀取
});
res.write(JSON.stringify('Hi! '+query.user));
res.end();
})
server.listen('9999');
console.log('Server is running at port 9999 .....');
這時候,我們翻開瀏覽器,接見 http://localhost:1111/client.html?user=jchermy,看到下面的頁面:
我們在1111端口,將user=jchermy
傳給9999端口,然後9999端口吸收到了我們的發送的信息並回傳了"Hi! jchermy"
.申明這兩個url能夠跨域互相通信!完成~
七、node.js 中間件跨域
這個計劃與nginx反向代辦非常相似,只是將nginx代辦效勞器換成了node效勞器。
目次:node-middleware/proxyserver.js
const express = require('express');
const proxy = require('http-proxy-middleware');
const app = express();
app.use('/login', proxy({
//代辦跨域的目的接口
target: 'http://localhost:5555',
changeOrigin: true,
//修正相應頭信息,完成跨域,並許可帶cookie
onProxyRes: function(proxyRes, req, res) {
res.header('Access-Control-Allow-Origin', 'http://localhost');
res.header('Access-Control-Allow-Credentials', 'true');
},
//修正相應信息中的cookie域名
cookieDomainRewrite: 'http://localhost'
}));
app.use(express.static( './public'));
app.listen(3333);
console.log('proxy server is listen at port 3333');
目次:node-middleware/server.js
const http = require('http');
const server = new http.Server();
const qs = require('querystring');
server.on('request', function(request, response) {
const query = require('url').parse(request.url, true).query;
response.writeHead(200, {
'Set-Cookie': 'name=amiee;Path:/;Domain:localhost:3333;Httponly'
});
response.write(`Hi, ${query.name} ! I come from localhost:5555`);
response.end();
})
server.listen('5555');
console.log('Server is running at port 5555 .....')
末了,接見http://localhost:3333/login?name=hahah,能夠看到:
八、webSocket
WebSocket protocol是HTML5一種新的協定。它完成了瀏覽器與效勞器全雙工通信,同時許可跨域通信,是server push手藝的一種很好的完成。
原生WebSocket API運用起來不太輕易,我們運用Socket.io,它很好地封裝了webSocket接口,供應了更簡樸、天真的接口,也對不支撐webSocket的瀏覽器供應了向下兼容。
起首,我們建立一個客戶端的html頁面。
目次:webSocket/public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>index</title>
</head>
<body>
<div>用戶輸入: <input type="text"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.js"></script>
<script>
window.onload = function(){
var socket = io('http://localhost:5555');
//銜接勝利處置懲罰
socket.on('connect', function(){
console.log('Server socket has established');
});
socket.on('disconnect', function() {
console.log('Server sockect has closed');
});
//監聽效勞端音訊
socket.on('message', function(msg) {
console.log('data from server ---->' +msg);
} )
document.getElementsByTagName('input')[0].onblur = function() {
socket.send(this.value);
};
}
</script>
</body>
</html>
將這個頁面布置在3333端口上。
目次:webSocket/client.js
const express = require('express');
const app = express();
app.use(express.static('./public'));
app.listen(3333);
console.log('client is running at port 3333....');
末了,建立一個效勞器,吸收客戶端的要求,並賦予返回值
目次: webSocket/server.js
const http = require('http');
const socket = require('socket.io');
//啟動http效勞
const server = http.createServer(function(req, res) {
res.writeHead(200, {
'Content-type': 'text/html'
});
res.end();
})
server.listen(5555);
console.log('server is running at port 5555');
const io = socket(server);
//監聽socket銜接
io.on('connection', function (client) {
//吸收音訊
client.on('message', function (msg) {
io.emit('message', `hello, ${msg}`);
console.log('data from client --->' + msg);
});
//斷開處置懲罰
client.on('disconnect', function() {
console.log('Client socket has closed');
});
});
將客戶端和效勞器端都跑起來,輸入一些字符,當鼠標落空核心后能夠在效勞器端5555端口的控制台看到:
這申明效勞器已收到了客戶端發送過去的字符。
此時在翻開客戶端頁面的控制台,能夠看到客戶端也收到了效勞器返回的字符:
結語
這個系列終究寫完啦,照樣那句話,有毛病和不合理的處所迎接人人斧正!假如文章對你有協助的話,迎接點贊和珍藏!!Github給個star就最好啦!=(//▽//)謝謝人人~