title: Socket.io in production returns 400 Bad Request error
body: <p>I am using Socket.IO in my application. The React client uses <a href="https://www.npmjs.com/package/socket.io-client" rel="nofollow noreferrer">socket.io-client</a> 4.1.3, and the Node.js server uses <a href="https://www.npmjs.com/package/socket.io" rel="nofollow noreferrer">socket.io</a> 4.1.3</p>
  <p>In the development environment on my local machine, everything works fine.</p>
  <p>The React app runs on http://localhost:3000, and connects to the server using:</p>
  <pre class="lang-js prettyprint-override"><code>import io from 'socket.io-client';
  const socket = io('http://localhost:5000/');
  </code></pre>
  <p>The Node.js server is configured as below:</p>
  <pre class="lang-js prettyprint-override"><code>const express = require('express');
  const app = express();
  const server = require('http').createServer(app);
  const cors = require('cors');
  const io = require('socket.io')(server, {
      cors: {
          origin: 'http://localhost:3000'
      },
      maxHttpBufferSize: '1e6'
  });
  app.set('io', io);
  app.use(express.static('public'));
  app.use(express.json({ limit: '7mb' }));
  app.use(cors({ origin: 'http://localhost:3000' }));
  server.listen(5000, () =&gt; console.log('Server started'));
  </code></pre>
  <p>In production, I am using Firebase to host the React app, in a subdirectory (e.g. <a href="https://www.example.com/app/" rel="nofollow noreferrer">https://www.example.com/app/</a>).</p>
  <p>In production, http://localhost:5000/ and http://localhost:3000 in the code above have also been changed to <a href="https://app.example.com" rel="nofollow noreferrer">https://app.example.com</a> and <a href="https://www.example.com/app" rel="nofollow noreferrer">https://www.example.com/app</a> respectively.</p>
  <p>My server uses Ubuntu 20.04, Nginx, and Let's Encrypt, with a server block set up as follows:</p>
  <pre><code>server {
  
      server_name app.example.com;
  
      location / {
          proxy_pass http://localhost:5000/;
      }
  
      listen [::]:443 ssl ipv6only=on; # managed by Certbot
      listen 443 ssl; # managed by Certbot
      ssl_certificate /etc/letsencrypt/live/app.example.com/fullchain.pem; # managed by Certbot
      ssl_certificate_key /etc/letsencrypt/live/app.example.com/privkey.pem; # managed by Certbot
      include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
      ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
  
  }server {
      if ($host = app.example.com) {
          return 301 https://$host$request_uri;
      } # managed by Certbot
  
  
      listen 80;
      listen [::]:80;
  
      server_name app.example.com;
      return 404; # managed by Certbot
  }
  </code></pre>
  <p>In Google Chrome, I was getting <em>No 'Access-Control-Allow-Origin' header is present on the requested resource</em> as an error. Changing the origin from <a href="https://www.example.com/app" rel="nofollow noreferrer">https://www.example.com/app</a> to * in the Node.js code fixed this.</p>
  <p>However, now I am getting the following error in my browser:</p>
  <p><em>POST <a href="https://app.example.com/socket.io/?EIO=4&amp;transport=polling&amp;t=NirW_WK&amp;sid=PmhwTyHRXOV4jWOdAAAF" rel="nofollow noreferrer">https://app.example.com/socket.io/?EIO=4&amp;transport=polling&amp;t=NirW_WK&amp;sid=PmhwTyHRXOV4jWOdAAAF</a> 400 (Bad Request)</em></p>
  <p>Why would this be?</p>
  <p>Thanks</p>