Search code examples
node.jsexpresssocket.ioalchemy

"socket.io" connection returns 404 when trying to access from localhost, integrated with node.js and react web frontend


I've managed to make this connection in a normal setup but when I'm trying to do this in a Classs-based way I'm getting a 404 error from the socket connection. Can anyone help me to understand what I'm doing wrong here?

The goal here is to make a successful socket connection with the front end which will receive events and notify. I'm using Alchemy SDK's notify webhook.

import express, { Application, Request, Response } from 'express';
import * as dotenv from 'dotenv';
import cors from 'cors';
import morgan from 'morgan';
import bodyParser, { json } from 'body-parser';
import homeRouter from './routes/home/homeRouter';
import balanceRouter from './routes/balance/balanceRouter';
import { Server } from 'socket.io';
import http from 'http';
import AlchemyClient from './controller/watcher/watcher.controller';
import mongoose from 'mongoose';
dotenv.config();
const PORT: number = process.env.HTTP_PORT as unknown as number;
const DB_URI: string = process.env.DB_URI as string;
class MainServer {
  private app: Application;
  private server: http.Server;
  private io: Server;

  constructor() {
    this.app = express();
    this.server = http.createServer(this.app);
    this.io = new Server(this.server, {
      cors: {
        origin: 'http://localhost:3000',
        methods: ['GET', 'POST'],
      },
    });
    this.connectToDatabase();
    this.configApp();
    this.configureMiddleware();
    this.configureRoutes();
  }
  private configApp(): void {
    this.app.use(express.json());
    this.app.use(cors());
    this.app.use(bodyParser.json());
    this.app.use(morgan(':method :url :status :response-time ms - :res[content-length]'));
  }

  private async connectToDatabase() {
    try {
      await mongoose.connect(DB_URI);
      console.log('Server connected...');
    } catch (error) {
      console.error(error);
    }
  }

  private configureMiddleware() {
    this.app.use(express.json());
    this.app.use(express.urlencoded({ extended: true }));
  }

  private configureRoutes(): void {
    this.app.use('/', homeRouter);
    this.app.use('/balances', balanceRouter);
    // this.app.get('/api/start-socket-connection', this.startSocketConnection);
    this.app.post('/alchemyhook', (req, res) => {
      // notification received from Alchemy from the webhook. Let the clients know.
      AlchemyClient.notificationReceived(this.io, req);
      res.status(200).end();
    });
  }

  public start(port: number): void {
    this.app.listen(port, () => {
      console.log(`Server started on port ${port}`);
    });
    this.io.on('connection', (socket) => {
      console.log('Client connected');
      socket.on('disconnect', () => console.log('Client disconnected'));
      socket.on('register address', (msg) => {
        //send address to Alchemy to add to notification
        AlchemyClient.registerAddress(msg);
      });
    });
  }
}

const server = new MainServer();
server.start(PORT);


Solution

  • I think instead of this.app.listen, it should be this.server.listen

    this.server.listen(port, () => {
          console.log(`Server started on port ${port}`);
     });