Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Using apollo-server-express, express-session and socketio – Cors issue present when socketio tries to connect on the client side

I am trying to use apollo-server-express to maintain a graphql endpoint and other endpoints to perform oAuth with twitter. I wanted to perform the oauth in the client in a way that a browser tab opens and a socket transmits a "MESSAGE" (as an example) from the callback to the server back to the main client window.

Here’s my index.js

import { ApolloServer } from "apollo-server-express";
import {
  ApolloServerPluginDrainHttpServer,
  ApolloServerPluginLandingPageLocalDefault,
} from "apollo-server-core";
import express from "express";
import session, { Session } from "express-session";
import crypto from "crypto";
import cors from "cors";
import http from "http";
import dotenv from "dotenv";
const socketio = require("socket.io");

dotenv.config();

import { twitterAuthClient, TWITTER_STATE } from "./utils/twitter";
import { schema } from "./schema";
import { prisma } from "./graphql/context";

declare module "express-serve-static-core" {
  interface Request {
    session: Session & {
      socketId: string;
    };
  }
}

(async () => {
  const app: express.Express = express();

  const httpServer = http.createServer(app);
  const io = socketio(httpServer);
  app.use(express.json());
  app.use(
    session({
      secret: [crypto.randomBytes(32).toString("hex")],
      resave: true,
      saveUninitialized: true,
    })
  );

  const plugins = [ApolloServerPluginDrainHttpServer({ httpServer })];
  plugins.push(ApolloServerPluginLandingPageLocalDefault());

  const server = new ApolloServer({
    plugins,
    schema,
    context: ({ req }) => {
      console.log(req.session);
      return {
        req,
        prisma,
      };
    },
    introspection: true, // disable in Prod
  });

  await server.start();

  const corsOptions = {
    origin: "http://localhost:3000",
  };

  server.applyMiddleware({
    app,
    cors: corsOptions,
  });

  // This custom middleware picks off the socket id (that was put on req.query)
  // and stores it in the session so we can send back the right info to the
  // right socket
  const addSocketIdToSession = (req: any, res: any, next: any) => {
    req.session.socketId = req.query.socketId;

    console.log(req.session.socketId);
    next();
  };

  app.get("/", async (_, res) => {
    res.send("Example Server");
  });

  app.get("/login", addSocketIdToSession, async (req, res) => {
    const authUrl = twitterAuthClient.generateAuthURL({
      state: TWITTER_STATE,
      code_challenge_method: "s256",
    });

    res.redirect(authUrl);
  });

  app.get("/callback", async (req, res) => {
    try {
      const { code, state } = req.query;
      if (state !== TWITTER_STATE)
        return res.status(500).send("State isn't matching");
      await twitterAuthClient.requestAccessToken(code as string);

      io.in(req.session.socketId).emit("user", "MESSAGE");

      res.end();
    } catch (error) {
      console.log(error);
    }
  });

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

  await new Promise<void>((resolve) => httpServer.listen({ port }, resolve));

  console.log(`Server ready at port: ${port} and path: ${server.graphqlPath}`);
})();

And on the client side I am using in my App.js in React

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

import io from "socket.io-client";

const API_URL = "http://127.0.0.1:4000";
const socket = io(API_URL);

But an issue persists, even though I am applying core options with applyMiddleware in apollo-server

Access to XMLHttpRequest at 'http://127.0.0.1:4000/socket.io/?EIO=3&transport=polling&t=O5gzz1z' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

On server side I am using

"apollo-server-express": "^3.9.0",
"express-session": "^1.17.3",
"socket.io": "^4.5.1",

On client side

"socket.io-client": "^4.5.1"

Any clues are appreciated. Thanks

>Solution :

It looks like you need to enable CORS for socket.io in order for it to work when using a different domain (and port).

Take a look at:
https://socket.io/docs/v4/handling-cors/ for more information about how to handle Socket.IO CORS

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading