inconshreveable / ngrok

Unified ingress for developers
https://ngrok.com
Other
24.12k stars 4.26k forks source link

React + Express + Socket.io + Ngrok #933

Closed mrbpp closed 9 months ago

mrbpp commented 10 months ago

Hello everyone,

before asking this question i tried everything but i still hit a dead end. So i need your help...

I have a React app (client-side) and Express (server-side). I am trying to make a connection using Socket.io.

/client : socket.io-client@4.7.2 /server : socket.io@4.7.2

// /server/server.js:

const express = require('express');
const { createServer } = require('http');
const { Server } = require('socket.io');
const socketioJwt = require('socketio-jwt');
const cors = require('cors');
const helmet = require('helmet');

const app = express();

// Enable CORS for all routes
app.use(cors());

// Enable Trust Proxy
app.set("trust proxy", 1);

// Use Helmet middleware to enhance security
app.use(helmet());

// Add this line to parse JSON data in incoming requests
app.use(express.json());

const httpServer = createServer(app);
const io = new Server(httpServer, {
  cors: {
    origin: "http://localhost:3000", // here i am putting the Ngork Client Url "https://ngrok-url.com"
    methods: ["GET", "POST"],
    credentials: true,
  },
});

const port = process.env.PORT || 4821;

io.use((socket, next) => {
  const clientIP = socket.handshake.address;

// Configure JWT authentication middleware
io.use(
  socketioJwt.authorize({
    secret: secretKey, // my secret from .env file
    handshake: true,
  })
);

// /client/src/App.js:

import React, { useState, useEffect } from 'react';
import io from 'socket.io-client';
import './styles.css'; 

const jwt = require('jsonwebtoken');
const token = jwt.sign(
  {
    username: "myUsername",
  },
  process.env.REACT_APP_JWT_SECRET
);
const socket = io("http:/localhost:4821", {. // here i am putting the ngork ServerUrl "https://ngrok-url.com"
  query: { token },
});

socket.on('connect', () => {
  console.log('Connected to the server');
});

socket.on('error', (error) => {
  console.error('WebSocket Error:', error);
});

NGROK Server: (on Virtual machine/Linux Ubuntu/Node.js LTS 18)

sudo ufw status, //(active), sudo ufw allow 4821, sudo ufw reload Starting /server - npm start; // script: nodemon node server.js Starting ngrok tunnel with - ngrok start server //ngrok.yml http localhost:4821 Get the Ngrok https SERVER URL Paste Ngrok Server URL in /client/App.js // type ctrl+c, npm start again App.js

NGROK Client: (on MAC)

Starting - /client/src/App.js - npm start Starting ngrok tunnel with - ngrok start client //ngrok.yml http localhost:3000 Get the Ngrok https CLIENT URL Paste Ngrok Client URL in /server/server.js // type "rs" in terminal to restart nodemon When i am using localhost:3000 (client) and localhost:4821 (server) i can see Socket.io connection, i do not have any problems. BUT when i am using Ngrok I have a BIG problem, I can not see Socket.io connection.

I do not have Errors in the browser console.

In the Network Tab (ALL), when i clicked on /socket... I saw:

Request URL:
https://f65b-185-213-154-249.ngrok-free.app/socket.io/?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InNhdG9zaGlAMjFubWlsbC5pbyIsImlhdCI6MTY5ODUwNjE1M30.v5hCOKlmMHf3RSEdXTumzO7PEtKzYz-XZrA6CqPsCkg&EIO=4&transport=polling&t=OjssoEr
Request Method:
GET
Status Code:
200 OK (from service worker)
Referrer Policy:
strict-origin-when-cross-origin
Access-Control-Allow-Origin:
*
Content-Length:
1396
Content-Security-Policy:
default-src 'self' https://cdn.ngrok.com 'unsafe-eval' 'unsafe-inline'; img-src data: w3.org/svg/2000
Content-Type:
text/html
Date:
Sat, 28 Oct 2023 15:15:55 GMT
Ngrok-Trace-Id:
7ca3e23723940ef090231cf42ad421a1
Referrer-Policy:
no-referrer
X-Content-Type-Options:
nosniff
Accept:
*/*
Referer:
https://ed5e-185-213-154-249.ngrok-free.app/
Sec-Ch-Ua:
"Chromium";v="118", "Brave";v="118", "Not=A?Brand";v="99"
Sec-Ch-Ua-Mobile:
?0
Sec-Ch-Ua-Platform:
"macOS"

In the Network Tab (WS), when I clicked on /socket... I saw only one sockjs-node, then when I clicked on sockjs-node:

Request URL:
wss://ed5e-185-213-154-249.ngrok-free.app/sockjs-node
Request Method:
GET
Status Code:
101 Switching Protocols
Connection:
Upgrade
Ngrok-Trace-Id:
58a6ffcdbd0cd5a1ef2d633378c24398
Sec-Websocket-Accept:
ONgwe/ms0WvXB6Tb2eIyPvx6dVo=
Upgrade:
websocket
Accept-Encoding:
gzip, deflate, br
Accept-Language:
en-GB,en-US;q=0.9,en;q=0.8
Cache-Control:
no-cache
Connection:
Upgrade
Cookie:
abuse_interstitial=ed5e-185-213-154-249.ngrok-free.app
Host:
ed5e-185-213-154-249.ngrok-free.app
Origin:
https://ed5e-185-213-154-249.ngrok-free.app
Pragma:
no-cache
Sec-Gpc:
1
Sec-Websocket-Extensions:
permessage-deflate; client_max_window_bits
Sec-Websocket-Key:
QQjVTB/9a2Ou5OcaPX2YnA==
Sec-Websocket-Version:
13
Upgrade:
websocket
User-Agent:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36

What I think is wrong is the fact that I do not have SSL certs for Ngrok (Let's Encrypt). I also think that I need to add two extra lines in the client/src/App.js file, but I am not sure if I really need to:

// /client/src/App.js
...
 const socket = io("http:/localhost:4821", {
  query: { token },
  withCredentials: true, // NEW LINE
  transport: [websockets, polling], // NEW LINE
});

IF YOU NEED ANY ADDITIONAL INFORMATION, PLEASE LET ME KNOW, AND I WILL GET BACK TO YOU ASAP.

PwccaCode commented 10 months ago

to wss you need ssl certs provided for ngrok otherwise the connection cannot be upgraded

mrbpp commented 9 months ago

Now I am using localtunel and everything works fine, when I will deploy my App I will add certs as you say and https instead of http, also 'secure: true,' to cors options.

I appreciate your help!