Apache Node.js Socket.io

由于系統(tǒng)是WAMP,由外包過渡過來的。在Apache設(shè)置反向代理比較不友善;且自chrome4.7以后,大部分socket請求必須基于SSL協(xié)議傳輸。


前提:給項目加個長連接,做個進度條。

困境:請求協(xié)議為HTTP, 如果加入SSL協(xié)議,這不僅增加一筆費用;對舊項目并不友好,php項目全是基于http的,而已Apache設(shè)置SSL估計又是折磨人。

解決:使用Apache設(shè)置反向代理,解決瀏覽器無法連接websocket的問題;使用localhost之前請求來解決安全性問題。


本文內(nèi)容

  • 項目環(huán)境技術(shù)棧
  • 后端Socket服務(wù)設(shè)計
  • 試錯過程
  • 提交方案
  • 運行項目
  • 參考網(wǎng)站

1.項目環(huán)境技術(shù)棧

  • 構(gòu)架時,后端代理前端壓縮包文件。
  • 長連接使用socket.io。

2.后端Socket服務(wù)設(shè)計

后端對外不開放,不需要使用反向代理。內(nèi)容如下所示(不全):

const express = require('express');
const http = require('http');
const socketio = require('socket.io');

const app = express();
const server = http.Server(app);
const io = socketio(server);
//加載前端頁面
app.use(express.static(path.join(__dirname, 'build')));

io.on('connection', (sock) => {
  console.log('Client connected');

  sock.on('heartbeat', (payload) => {
    payload.nodeName = name;
    sock.emit('heartbeat', payload);
  });

  sock.on('disconnect', () => {
    console.log('Socket Disconnected');
  });
});

server.listen(+port, '0.0.0.0', (err) => {
  console.log(`Node [${name}] listens on http://127.0.0.1:${port}.`);
});

3.試錯過程

由于之前沒做過,好尷尬了??戳藥讉€小時socket.io文檔直接使用了,所以踩的坑會比較多。

  • 由于chrome4.7后,對安全策略進行變化 。先了解瀏覽器對websocket的長連接的策略。

node代理
使用node http-proxy-middleware代理socket過程,在本地(都是基本localhost)完美運行。然后上傳運行代理,并開放外網(wǎng)端口,運行結(jié)果如下所示:

[HPM] Proxy created: /  ->  http://localhost:8787
[HPM] Subscribed to http-proxy events:  [ 'error', 'close' ]
[HPM] Proxy created: /  ->  http://localhost:8787
[HPM] Subscribed to http-proxy events:  [ 'error', 'close' ]
  • 顯示代理成功,在服務(wù)器測試socket連接正常。但使用外網(wǎng)訪問時,如下的錯誤
Uncaught (in promise) DOMException: Only secure origins are allowed. http://goo.gl/lq4gCo
  • 分析過程:
  1. 在服務(wù)器端測試時,可以通過是因為:它們之間是localhost請求,能過瀏覽器安全策略。
  2. 服務(wù)器外網(wǎng)地址跟localhost在服務(wù)器在有網(wǎng)卡代理,localhost與外網(wǎng)交互,沒安全策略的,它也相當于一個本地請求。
  3. 當在外網(wǎng)訪問網(wǎng)頁端時,網(wǎng)頁在"/"鏈接中,地址是外網(wǎng)地址。外網(wǎng)與localhost將無法通過瀏覽器安全策略。

使用Apache代理過程

  • 先實現(xiàn)一個小目標,實現(xiàn)一個簡單的Http反向代理。
#不給別人get到你的代理
ProxyRequests off 
    <Location />
        ProxyPass http://127.0.0.1:30003/
        ProxyPassReverse /
    </Location>

  • 那么接下去代理,想下Apache代理比較全的帖子,我擦,完全沒有提到Socket,就加入個mod_proxy_connect,說不定以后能使用SSL呢。
  • 那只有去官網(wǎng)找,意淫術(shù),socket的請求協(xié)議為WS,去httpd.conf搜下(找下)proxy-ws*,果然找到mod_proxy_wstunnel,就是這貨了。
  • 接下去的看,只能在2.4.5以上版本使用。呸,然后查下2.4.3才發(fā)行。直接用別管它。
    Compatibility: |Available in httpd 2.4.5 and later
  • 在httpd.conf文件中,加載這模塊
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so

WAMP

  • 有時,沒什么毛病,它就是不給你運行。這個迷之原因,炸了沒。別扯什么底層代理實現(xiàn)過程。
  • 使用顏色分析過程,一般是:紅色->橙色->綠色。不行的話,紅色那狀態(tài)會比較快,然后停到橙色。
  • 使用重復啟動法,重復重啟。當紅色停留比較久時,那就可能成功了。

4.提交方案

下面將使用Apache反向代理,使網(wǎng)頁端與API接口變成localhost間的請求,原理圖如下所示,網(wǎng)頁端服務(wù)跟API服務(wù)將在內(nèi)部服務(wù)器中:


1. 將網(wǎng)頁端服務(wù)使用反向代理出來

//httpd.conf
Listen 30003
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so
LoadModule proxy_http_module modules/mod_proxy_http.so

//httpd-vhosts.conf

<VirtualHost *:30003>
    RewriteEngine On
    RewriteCond %{HTTP:Connection} Upgrade [NC]
    RewriteCond %{HTTP:Upgrade} websocket [NC]
    RewriteRule /(.*) ws://127.0.0.1:3030/$1 [P,L]

    ProxyRequests off
    <Location />
        ProxyPass http://127.0.0.1:3030/
        ProxyPassReverse /
    </Location>
</VirtualHost>

2.前后端分離,前端使用socket.io-client,代碼如下所示:

import openSocket from 'socket.io-client';
const socket = openSocket(); //不用設(shè)置任意參數(shù)

 socket.on('heartbeat', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });

5.運行項目

  • 訪問服務(wù)器端口30003地址,其實是反向訪問localhost:3000。localhost地址之間socket長連接無fuck。
  • 不安全是Http協(xié)議的長連接。



6.參考網(wǎng)站

如果socket請求跨源,一定要有SSL設(shè)置?,不太清楚

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容