Browse Source

Added simple websocket

Alexander Musikhin 11 months ago
parent
commit
9c0eebb170

+ 32 - 29
composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "dfa7e253cb60313d37705e47dff758ae",
+    "content-hash": "00648a7052ad5efdfbed2952a9ec8d54",
     "packages": [
         {
             "name": "brick/math",
@@ -2174,16 +2174,16 @@
         },
         {
             "name": "nesbot/carbon",
-            "version": "3.8.2",
+            "version": "3.8.3",
             "source": {
                 "type": "git",
                 "url": "https://github.com/briannesbitt/Carbon.git",
-                "reference": "e1268cdbc486d97ce23fef2c666dc3c6b6de9947"
+                "reference": "f01cfa96468f4c38325f507ab81a4f1d2cd93cfe"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/e1268cdbc486d97ce23fef2c666dc3c6b6de9947",
-                "reference": "e1268cdbc486d97ce23fef2c666dc3c6b6de9947",
+                "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/f01cfa96468f4c38325f507ab81a4f1d2cd93cfe",
+                "reference": "f01cfa96468f4c38325f507ab81a4f1d2cd93cfe",
                 "shasum": ""
             },
             "require": {
@@ -2215,10 +2215,6 @@
             ],
             "type": "library",
             "extra": {
-                "branch-alias": {
-                    "dev-master": "3.x-dev",
-                    "dev-2.x": "2.x-dev"
-                },
                 "laravel": {
                     "providers": [
                         "Carbon\\Laravel\\ServiceProvider"
@@ -2228,6 +2224,10 @@
                     "includes": [
                         "extension.neon"
                     ]
+                },
+                "branch-alias": {
+                    "dev-2.x": "2.x-dev",
+                    "dev-master": "3.x-dev"
                 }
             },
             "autoload": {
@@ -2276,7 +2276,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2024-11-07T17:46:48+00:00"
+            "time": "2024-12-21T18:03:19+00:00"
         },
         {
             "name": "nette/schema",
@@ -5653,31 +5653,33 @@
         },
         {
             "name": "tijsverkoyen/css-to-inline-styles",
-            "version": "v2.2.7",
+            "version": "v2.3.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git",
-                "reference": "83ee6f38df0a63106a9e4536e3060458b74ccedb"
+                "reference": "0d72ac1c00084279c1816675284073c5a337c20d"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/83ee6f38df0a63106a9e4536e3060458b74ccedb",
-                "reference": "83ee6f38df0a63106a9e4536e3060458b74ccedb",
+                "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/0d72ac1c00084279c1816675284073c5a337c20d",
+                "reference": "0d72ac1c00084279c1816675284073c5a337c20d",
                 "shasum": ""
             },
             "require": {
                 "ext-dom": "*",
                 "ext-libxml": "*",
-                "php": "^5.5 || ^7.0 || ^8.0",
-                "symfony/css-selector": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0 || ^7.0"
+                "php": "^7.4 || ^8.0",
+                "symfony/css-selector": "^5.4 || ^6.0 || ^7.0"
             },
             "require-dev": {
-                "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.0 || ^7.5 || ^8.5.21 || ^9.5.10"
+                "phpstan/phpstan": "^2.0",
+                "phpstan/phpstan-phpunit": "^2.0",
+                "phpunit/phpunit": "^8.5.21 || ^9.5.10"
             },
             "type": "library",
             "extra": {
                 "branch-alias": {
-                    "dev-master": "2.2.x-dev"
+                    "dev-master": "2.x-dev"
                 }
             },
             "autoload": {
@@ -5700,9 +5702,9 @@
             "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles",
             "support": {
                 "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues",
-                "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.2.7"
+                "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/v2.3.0"
             },
-            "time": "2023-12-08T13:03:43+00:00"
+            "time": "2024-12-21T16:25:41+00:00"
         },
         {
             "name": "vlucas/phpdotenv",
@@ -6997,16 +6999,16 @@
         },
         {
             "name": "phpunit/phpunit",
-            "version": "11.5.1",
+            "version": "11.5.2",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
-                "reference": "2b94d4f2450b9869fa64a46fd8a6a41997aef56a"
+                "reference": "153d0531b9f7e883c5053160cad6dd5ac28140b3"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2b94d4f2450b9869fa64a46fd8a6a41997aef56a",
-                "reference": "2b94d4f2450b9869fa64a46fd8a6a41997aef56a",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/153d0531b9f7e883c5053160cad6dd5ac28140b3",
+                "reference": "153d0531b9f7e883c5053160cad6dd5ac28140b3",
                 "shasum": ""
             },
             "require": {
@@ -7020,13 +7022,13 @@
                 "phar-io/manifest": "^2.0.4",
                 "phar-io/version": "^3.2.1",
                 "php": ">=8.2",
-                "phpunit/php-code-coverage": "^11.0.7",
+                "phpunit/php-code-coverage": "^11.0.8",
                 "phpunit/php-file-iterator": "^5.1.0",
                 "phpunit/php-invoker": "^5.0.1",
                 "phpunit/php-text-template": "^4.0.1",
                 "phpunit/php-timer": "^7.0.1",
                 "sebastian/cli-parser": "^3.0.2",
-                "sebastian/code-unit": "^3.0.1",
+                "sebastian/code-unit": "^3.0.2",
                 "sebastian/comparator": "^6.2.1",
                 "sebastian/diff": "^6.0.2",
                 "sebastian/environment": "^7.2.0",
@@ -7078,7 +7080,7 @@
             "support": {
                 "issues": "https://github.com/sebastianbergmann/phpunit/issues",
                 "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
-                "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.1"
+                "source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.2"
             },
             "funding": [
                 {
@@ -7094,7 +7096,7 @@
                     "type": "tidelift"
                 }
             ],
-            "time": "2024-12-11T10:52:48+00:00"
+            "time": "2024-12-21T05:51:08+00:00"
         },
         {
             "name": "sebastian/cli-parser",
@@ -8200,7 +8202,8 @@
     "prefer-stable": true,
     "prefer-lowest": false,
     "platform": {
-        "php": "^8.2"
+        "php": "^8.2",
+        "ext-pdo": "*"
     },
     "platform-dev": {},
     "plugin-api-version": "2.6.0"

+ 2 - 0
config/app.php

@@ -53,6 +53,8 @@ return [
     */
 
     'url' => env('APP_URL', 'http://localhost'),
+    'addr' => env('APP_ADDR', 'http://localhost'),
+    'ws_port' => env('WS_PORT', '3000'),
 
     /*
     |--------------------------------------------------------------------------

+ 1 - 1
docker-compose.debug.yml

@@ -45,7 +45,7 @@ services:
     websocket:
         command: '/bin/sh -c ''node --inspect=0.0.0.0:9229 server'''
         ports: !override
-            - ${WS_PORT:-3000}:3000
+            - ${WS_PORT:-3000}:9000
             - ${WS_DEBUG_PORT:-9229}:9229
 
     redis:

+ 9 - 5
docker-compose.yml

@@ -75,7 +75,6 @@ services:
         command: '/bin/sh -c ''while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g "daemon off;"'''
         ports:
             - ${WEB_PORT:-80}:80
-#            - 5172:5173
         volumes:
             - ./public:/var/frontend
             - ./:/var/www
@@ -111,8 +110,10 @@ services:
 
     websocket:
         build:
-            context: docker/websocket
+            context: docker/simple-ws
             dockerfile: Dockerfile
+        volumes:
+            - ./docker/simple-ws/server.js:/app/server.js
         restart: unless-stopped
         environment:
             - JWT_SECRET=${JWT_SECRET}
@@ -120,7 +121,7 @@ services:
         tty: true
         command: '/bin/sh -c ''node server'''
         ports:
-            - ${WS_PORT:-3000}:3000
+            - ${WS_PORT:-3000}:9000
         networks:
             - cpa-network
         depends_on:
@@ -135,8 +136,11 @@ services:
         networks:
             - cpa-network
         healthcheck:
-            test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ]
-
+            test: redis-cli --raw --pass $$REDIS_PASSWORD incr ping
+            start_period: 1s
+            interval: 1s
+            timeout: 3s
+            retries: 255
 #    minio:
 #        image: minio/minio
 #        volumes:

+ 1 - 1
docker/websocket/Dockerfile → docker/simple-ws/Dockerfile

@@ -2,5 +2,5 @@ FROM node
 RUN mkdir app
 COPY ./ /app
 WORKDIR /app
-EXPOSE 3000
+EXPOSE 9000
 RUN npm i

+ 12 - 0
docker/simple-ws/package.json

@@ -0,0 +1,12 @@
+{
+  "name": "simple-ws",
+  "version": "1.0.0",
+  "description": "Simple ws server",
+  "license": "MIT",
+  "dependencies": {
+    "ws": "^8.18.0",
+    "dotenv": "^16.0.1",
+    "ioredis": "^5.0.6",
+    "utf-8-validate": "^6.0.5"
+  }
+}

+ 61 - 0
docker/simple-ws/server.js

@@ -0,0 +1,61 @@
+const WebSocket = require('ws');
+const Redis = require('ioredis');
+
+
+const wsServer = new WebSocket.Server({ port: 9000 });
+
+const redis = new Redis({
+    port: 6379,
+    host: "redis",
+    username: "default",
+    password: process.env.REDIS_PASSWORD,
+    db: 0,
+});
+
+
+
+wsServer.on('connection', onConnect);
+
+function onConnect(wsClient) {
+    console.log('New connection');
+
+    wsClient.on('close', function() {
+        console.log('Connection closed');
+    });
+
+    wsClient.on('message', function(message) {
+        console.log(message);
+        try {
+            const jsonMessage = JSON.parse(message);
+            switch (jsonMessage.action) {
+                case 'ECHO':
+                    wsClient.send(jsonMessage.data);
+                    break;
+                case 'PING':
+                    setTimeout(function() {
+                        wsClient.send('PONG');
+                    }, 2000);
+                    break;
+                default:
+                    console.log('Неизвестная команда');
+                    break;
+            }
+        } catch (error) {
+            console.log('Ошибка', error);
+        }
+    });
+
+    redis.subscribe("actions", (err, count) => {
+        if (err) console.error(err.message);
+        console.log(`Subscribed to ${count} channels.`);
+    });
+
+    redis.on("message", function (channel, data) {
+        wsClient.send(data);
+        data = JSON.parse(data).data;
+        console.log(`send new message to user ${data.user_id} in the channel '${channel}'.`);
+    });
+
+}
+
+

+ 0 - 14
docker/websocket/package.json

@@ -1,14 +0,0 @@
-{
-    "name": "socket-chat-example",
-    "version": "0.0.1",
-    "description": "The socket.io server",
-    "type": "module",
-    "license": "MIT",
-    "dependencies": {
-        "dotenv": "^16.0.1",
-        "fs": "^0.0.1-security",
-        "ioredis": "^5.0.6",
-        "jsonwebtoken": "9.0.2",
-        "socket.io": "4.7.2"
-    }
-}

+ 0 - 76
docker/websocket/server.js

@@ -1,76 +0,0 @@
-import { Server } from "socket.io";
-import { Redis } from "ioredis";
-import jwt from "jsonwebtoken";
-
-const jwtSecret = process.env.JWT_SECRET;
-const port = process.env.PORT || 3000;
-const io = new Server(port, {
-    cors: {
-        origin: "*",
-        credentials: true,
-    },
-});
-const redis = new Redis({
-    port: 6379,
-    host: "redis",
-    username: "default",
-    password: process.env.REDIS_PASSWORD,
-    db: 0,
-});
-
-io.engine.use((req, res, next) => {
-    const isHandshake = req._query.sid === undefined;
-
-    if (!isHandshake) {
-        return next();
-    }
-
-    const header = req.headers["authorization"];
-
-    if (!header) {
-        return next(new Error("no token"));
-    }
-
-    if (!header.startsWith("Bearer ")) {
-        return next(new Error("invalid token"));
-    }
-
-    const token = header.substring(7);
-
-    jwt.verify(token, jwtSecret, (err, decoded) => {
-        if (err) {
-            return next(new Error("invalid token"));
-        }
-        req.decodedToken = decoded;
-        next();
-    });
-
-});
-
-io.on("connection", (socket) => {
-    console.log(`connected with transport ${socket.conn.transport.name} and socket ${socket.id}`);
-
-    socket.conn.on("upgrade", (transport) => {
-        console.log(`transport upgraded to ${transport.name}`);
-    });
-
-    socket.on("disconnect", (reason) => {
-        console.log(`disconnected ${socket.id} due to ${reason}`);
-    });
-
-    if(socket.request.decodedToken){
-        let user_id = parseInt(socket.request.decodedToken.sub)
-        socket.join(user_id);
-    }
-});
-
-redis.subscribe("actions", (err, count) => {
-    if (err) console.error(err.message);
-    console.log(`Subscribed to ${count} channels.`);
-});
-
-redis.on("message", function (channel, data) {
-    data = JSON.parse(data).data;
-    io.to(data.user_id).emit(data.action, data);
-    console.log(`send new message to user ${data.user_id} in the channel '${channel}'.`);
-});

+ 31 - 0
resources/views/layouts/app.blade.php

@@ -104,6 +104,37 @@
                     })
                 }, 3000);
             }
+
+            let user = {{ auth()->user()?->id ?? 0}}; // zero is not logged in user
+
+            if(user > 0) {
+                let socket = new WebSocket('{{ config('app.addr') . ':' . config('app.ws_port') }}');
+                socket.onopen = function() {
+                    console.log("[WS] Connected. Listen messages for user " + user);
+                };
+
+                socket.onmessage = function(event) {
+                    let received = JSON.parse(event.data);
+                    if(parseInt(received.data.user_id) === user) {
+                        console.log(received);
+                        console.log(`[WS] Received data action: ${received.data.action}. Message: ${received.data.message}`);
+                        alert(received.data.message);
+                    }
+
+                };
+
+                socket.onclose = function(event) {
+                    if (event.wasClean) {
+                        console.log(`[WS] Closed clear, code=${event.code} reason=${event.reason}`);
+                    } else {
+                        console.log('[WS] Connection lost', event);
+                    }
+                };
+                socket.onerror = function(error) {
+                    console.log(`[error] ${error}`);
+                };
+
+            }
         });
     </script>