You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DigitalOcean上NodeJS+SocketIO应用本地访问CORS报错求助

问题

我尝试从本地环境(http://localhost:3000)访问部署在DigitalOcean上的NodeJS应用,却持续触发CORS报错,具体错误如下:

Access to XMLHttpRequest at 'url.ondigitalocean.app/socket.io/?EIO=4&transport=polling&t=OFlEPJW' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request.
url.ondigitalocean.app/socket.io/?EIO=4&transport=polling&t=OFlEPJW:1 Failed to load resource: net::ERR_FAILED

其中https://admin.socket.io可正常访问,但本地连接被拒绝。以下是我的服务端代码、客户端代码及服务器配置:

服务端代码

const http = require("http");
const express = require("express");
const {instrument} = require('@socket.io/admin-ui')
const {jwtDecode, jwtVerify, resignJwt} = require('jwt-js-decode')

const secret = process.env.JWT_SECRET

const app = express()

const server = http.createServer(app)
const io = require("socket.io")(server, {
  cors: {
    origin: [
      "https://admin.socket.io",
      "http://localhost:3000/",
      "http://localhost:3000",
      "http://127.0.0.1:3000",
      "http://127.0.0.1:3000/",
      "http://localhost:3001",
      "http://localhost:3001/"
    ],
    credentials: true,
  },
});

客户端代码

import { io } from "socket.io-client";

const token = window.localStorage.getItem('TOKEN') || window.sessionStorage.getItem('TOKEN')

const ioSocket = io('url.ondigitalocean.app', {
    withCredentials: true,
    transportOptions: {
        polling: {
            extraHeaders: {
                'authorization': `${token}`,
            },
        },
    },
});

export const socket = ioSocket

服务器配置

name: dolphin-app
region: fra
services:
- cors:
    allow_headers:
    - '*'
    allow_methods:
    - GET
    - OPTIONS
    - POST
    - PUT
    - PATCH
    - DELETE
    - HEAD
    - CONNECT
    - TRACE
    allow_origins:
    - exact: http://localhost:3000
    - prefix: http://localhost:3000
    - prefix: http://127.0.0.1:3000
    - prefix: http://localhost
  environment_slug: node-js
  github:
    branch: main
    deploy_on_push: true
    repo: 1
  http_port: 8080
  instance_count: 1
  instance_size_slug: basic-xs
  name: websocket
  routes:
  - path: /
  run_command: npm start
  source_dir: /
问题分析与解决方案

1. 客户端连接地址缺少HTTPS协议前缀

客户端代码中连接地址url.ondigitalocean.app未指定https://,浏览器会默认使用本地页面的HTTP协议发起请求,而DigitalOcean的服务会强制将HTTP请求重定向到HTTPS。但CORS预请求(OPTIONS)不允许重定向,直接触发报错。

修复方案:
修改客户端连接地址为完整HTTPS URL:

const ioSocket = io('https://url.ondigitalocean.app', {
    withCredentials: true,
    transportOptions: {
        polling: {
            extraHeaders: {
                'authorization': `${token}`,
            },
        },
    },
});

2. 服务端CORS配置冗余

服务端Socket.IO的cors配置中同时包含带斜杠和不带斜杠的origin(如http://localhost:3000/和http://localhost:3000),属于重复配置,虽然Socket.IO能兼容,但会增加维护成本。另外,DigitalOcean服务级CORS配置与代码层配置可能存在冲突,建议统一在一处配置。

优化方案:
精简服务端origin列表,去掉重复项:

const io = require("socket.io")(server, {
  cors: {
    origin: [
      "https://admin.socket.io",
      "http://localhost:3000",
      "http://127.0.0.1:3000",
      "http://localhost:3001"
    ],
    credentials: true,
  },
});

3. 验证服务监听端口匹配

确保服务端代码中监听的端口与DigitalOcean配置的http_port: 8080一致,若服务端未显式指定监听端口,需补充:

server.listen(8080, () => {
  console.log('Server running on port 8080');
});

内容的提问来源于stack exchange,提问作者Sasha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 10:40:35