Apache Node.js Socket.io

2018-07-28  本文已影响0人  jebirth

由于系统是WAMP,由外包过渡过来的。在Apache设置反向代理比较不友善;且自chrome4.7以后,大部分socket请求必须基于SSL协议传输。


前提:给项目加个长连接,做个进度条。

困境:请求协议为HTTP, 如果加入SSL协议,这不仅增加一笔费用;对旧项目并不友好,php项目全是基于http的,而已Apache设置SSL估计又是折磨人。

解决:使用Apache设置反向代理,解决浏览器无法连接websocket的问题;使用localhost之前请求来解决安全性问题。


本文内容

1.项目环境技术栈

2.后端Socket服务设计

后端对外不开放,不需要使用反向代理。内容如下所示(不全):

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文档直接使用了,所以踩的坑会比较多。


node代理
使用node http-proxy-middleware代理socket过程,在本地(都是基本localhost)完美运行。然后上传运行代理,并开放外网端口,运行结果如下所示:

[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' ]
Uncaught (in promise) DOMException: Only secure origins are allowed. http://goo.gl/lq4gCo
  1. 在服务器端测试时,可以通过是因为:它们之间是localhost请求,能过浏览器安全策略。
  2. 服务器外网地址跟localhost在服务器在有网卡代理,localhost与外网交互,没安全策略的,它也相当于一个本地请求。
  3. 当在外网访问网页端时,网页在"/"链接中,地址是外网地址。外网与localhost将无法通过浏览器安全策略。

使用Apache代理过程

#不给别人get到你的代理
ProxyRequests off 
    <Location />
        ProxyPass http://127.0.0.1:30003/
        ProxyPassReverse /
    </Location>

LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so

WAMP


4.提交方案

下面将使用Apache反向代理,使网页端与API接口变成localhost间的请求,原理图如下所示,网页端服务跟API服务将在内部服务器中:


1. 将网页端服务使用反向代理出来
//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(); //不用设置任意参数

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

5.运行项目


6.参考网站

如果socket请求跨源,一定要有SSL设置?,不太清楚

上一篇 下一篇

猜你喜欢

热点阅读