最新消息:Welcome to the puzzle paradise for programmers! Here, a well-designed puzzle awaits you. From code logic puzzles to algorithmic challenges, each level is closely centered on the programmer's expertise and skills. Whether you're a novice programmer or an experienced tech guru, you'll find your own challenges on this site. In the process of solving puzzles, you can not only exercise your thinking skills, but also deepen your understanding and application of programming knowledge. Come to start this puzzle journey full of wisdom and challenges, with many programmers to compete with each other and show your programming wisdom! Translated with DeepL.com (free version)

javascript - WebSocket notifications not working with deployed Render URL but working locally - Stack Overflow

matteradmin6PV0评论

I am experiencing issues with WebSocket in my code. When using the deployed URL from Render (), I do not receive notifications on the frontend. However, when using http://localhost:5000, the notifications work as expected on the frontend.

import {
  addNotification,
  clearNotifications,
} from '@/features/notification/notificationSlice';
import { FC, useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import socketIo from 'socket.io-client';

interface SocketComponentProps {
  children: React.ReactNode;
}

const SocketComponent: FC<SocketComponentProps> = ({ children }) => {
  const dispatch = useDispatch();

  const { userInfo } = useSelector((state: any) => state.user);
  const currentUserId = userInfo?.user?.id;
  const messages = useSelector((state: any) => state.chat.conversations);

  useEffect(() => {
    const socket = socketIo('', {
      transports: ['websocket'],
    });

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

    socket.emit('joinNotifications', { userId: currentUserId });
    socket.on('notification', (notification) => {
      console.log('Notification received:', notification);
      dispatch(addNotification(notification));
    });

    return () => {
      socket.disconnect();
      socket.off('notification');
    };
  }, [messages, dispatch]);

  return <>{children}</>;
};

export default SocketComponent;

Here is the backend code

const { Server } = require('socket.io');

const app = express();enter code here

app.use('../public', express.static('public'));
app.use(bodyParser.json());
app.use(cors());

app.use(
  '/graphql',
  graphqlHTTP(async (req, res) => {
    const user = await authMiddleware(req, res);
    console.log({ user });
    return {
      schema,
      graphiql: true,
      context: {
        User,
        Property,
        currentUser: user,
        io,
      },
    };
  }),
);
const server = http.createServer(app);
const io = new Server(server, {
  cors: {
    origin: '*',
    methods: ['GET', 'POST'],
  },
});

io.on('connection', (socket) => {
  socket.on('joinNotifications', ({ userId }) => {
    socket.join(userId);
  });
});

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

if (!module.parent) {
  server.listen(port, () => {
    logger.info(`server running on port ${port}`);
  });
}

module.exports = server;

here is the notification handler
const sendNotification = (io, userId, title, body, url = null) => {
  try {
    const notification = {
      title,
      body,
      timestamp: new Date(),
      read: false,
    };

    // Add the URL if provided
    if (url) {
      notification.url = url;
    }

    // Emit the notification to the user
    io.to(userId).emit('notification', notification);

    console.log({ notification });
  } catch (error) {
    console.error(`Error sending notification to user ${userId}:`, error);
  }
};

module.exports = sendNotification;

here is the graqhl mutation
requestApproval: {
      type: ApprovalType,
      args: {
        bookingId: { type: GraphQLNonNull(GraphQLID) },
        userId: { type: GraphQLNonNull(GraphQLID) },
        message: { type: GraphQLString },
      },
      resolve: async (parent, args, context) => {
        const { io } = context;

        //<--------- create an approval based on the booking id ---------->
        const approval = new Approval({
          booking: args.bookingId,
          user: args.userId,
          message: args.message,
        });

        const createdApproval = await approval.save();
        const booking = await Booking.findById(args.bookingId).populate('user property');
        //<---------- find the host who owns that property ---------->
        const host = await User.findById(booking.property.user);
        const hostEmail = host.email;

        const baseUrl = process.env.NODE_ENV === 'production' ? process.env.PROD_URL : process.env.DEV_URL;
        const manageShortletUrl = `${baseUrl}/manage-shortlets`;
        //<---------- email option for booking request ---------->
        const bookingDetails = {
          ...booking._doc,
          startDate: moment(booking.startDate).format('DD MMMM YYYY'),
          endDate: moment(booking.endDate).format('DD MMMM YYYY'),
        };
        const hostMail = {
          From: '[email protected]',
          To: hostEmail,
          Subject: `New Booking Request for ${booking.property.title}`,
          HtmlBody: BOOKING_REQUEST_TEMPLATE(host, bookingDetails, manageShortletUrl),
        };

        const notificationLink = `/review-booking/${booking.property._id.toString()}`;

        try {
          const result = await client.sendEmail(hostMail);

          sendNotification(
            io,
            host._id.toString(),
            'Booking Request',
            `You have a new booking request for your property ${booking.property.title}.`,
            notificationLink,
          );

          console.log('sent');
        } catch (error) {
          console.error('Error sending email to host:', error);
        }

        return createdApproval;
      },
    },

I am experiencing issues with WebSocket in my code. When using the deployed URL from Render (https://polis-backend-test.onrender), I do not receive notifications on the frontend. However, when using http://localhost:5000, the notifications work as expected on the frontend.

import {
  addNotification,
  clearNotifications,
} from '@/features/notification/notificationSlice';
import { FC, useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import socketIo from 'socket.io-client';

interface SocketComponentProps {
  children: React.ReactNode;
}

const SocketComponent: FC<SocketComponentProps> = ({ children }) => {
  const dispatch = useDispatch();

  const { userInfo } = useSelector((state: any) => state.user);
  const currentUserId = userInfo?.user?.id;
  const messages = useSelector((state: any) => state.chat.conversations);

  useEffect(() => {
    const socket = socketIo('https://polis-backend-test.onrender', {
      transports: ['websocket'],
    });

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

    socket.emit('joinNotifications', { userId: currentUserId });
    socket.on('notification', (notification) => {
      console.log('Notification received:', notification);
      dispatch(addNotification(notification));
    });

    return () => {
      socket.disconnect();
      socket.off('notification');
    };
  }, [messages, dispatch]);

  return <>{children}</>;
};

export default SocketComponent;

Here is the backend code

const { Server } = require('socket.io');

const app = express();enter code here

app.use('../public', express.static('public'));
app.use(bodyParser.json());
app.use(cors());

app.use(
  '/graphql',
  graphqlHTTP(async (req, res) => {
    const user = await authMiddleware(req, res);
    console.log({ user });
    return {
      schema,
      graphiql: true,
      context: {
        User,
        Property,
        currentUser: user,
        io,
      },
    };
  }),
);
const server = http.createServer(app);
const io = new Server(server, {
  cors: {
    origin: '*',
    methods: ['GET', 'POST'],
  },
});

io.on('connection', (socket) => {
  socket.on('joinNotifications', ({ userId }) => {
    socket.join(userId);
  });
});

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

if (!module.parent) {
  server.listen(port, () => {
    logger.info(`server running on port ${port}`);
  });
}

module.exports = server;

here is the notification handler
const sendNotification = (io, userId, title, body, url = null) => {
  try {
    const notification = {
      title,
      body,
      timestamp: new Date(),
      read: false,
    };

    // Add the URL if provided
    if (url) {
      notification.url = url;
    }

    // Emit the notification to the user
    io.to(userId).emit('notification', notification);

    console.log({ notification });
  } catch (error) {
    console.error(`Error sending notification to user ${userId}:`, error);
  }
};

module.exports = sendNotification;

here is the graqhl mutation
requestApproval: {
      type: ApprovalType,
      args: {
        bookingId: { type: GraphQLNonNull(GraphQLID) },
        userId: { type: GraphQLNonNull(GraphQLID) },
        message: { type: GraphQLString },
      },
      resolve: async (parent, args, context) => {
        const { io } = context;

        //<--------- create an approval based on the booking id ---------->
        const approval = new Approval({
          booking: args.bookingId,
          user: args.userId,
          message: args.message,
        });

        const createdApproval = await approval.save();
        const booking = await Booking.findById(args.bookingId).populate('user property');
        //<---------- find the host who owns that property ---------->
        const host = await User.findById(booking.property.user);
        const hostEmail = host.email;

        const baseUrl = process.env.NODE_ENV === 'production' ? process.env.PROD_URL : process.env.DEV_URL;
        const manageShortletUrl = `${baseUrl}/manage-shortlets`;
        //<---------- email option for booking request ---------->
        const bookingDetails = {
          ...booking._doc,
          startDate: moment(booking.startDate).format('DD MMMM YYYY'),
          endDate: moment(booking.endDate).format('DD MMMM YYYY'),
        };
        const hostMail = {
          From: '[email protected]',
          To: hostEmail,
          Subject: `New Booking Request for ${booking.property.title}`,
          HtmlBody: BOOKING_REQUEST_TEMPLATE(host, bookingDetails, manageShortletUrl),
        };

        const notificationLink = `/review-booking/${booking.property._id.toString()}`;

        try {
          const result = await client.sendEmail(hostMail);

          sendNotification(
            io,
            host._id.toString(),
            'Booking Request',
            `You have a new booking request for your property ${booking.property.title}.`,
            notificationLink,
          );

          console.log('sent');
        } catch (error) {
          console.error('Error sending email to host:', error);
        }

        return createdApproval;
      },
    },

Share Improve this question asked Nov 18, 2024 at 16:40 Favour SamsonFavour Samson 212 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

Most likely it is related to the hosting (or server) configuration. Some hosting (like Vercel) does not support sockets. https://vercel/guides/do-vercel-serverless-functions-support-websocket-connections

Post a comment

comment list (0)

  1. No comments so far