【问题标题】:Angular app cant connect to NodeJS/SocketIO backend cors issue?Angular 应用程序无法连接到 NodeJS/SocketIO 后端 cors 问题?
【发布时间】:2021-03-02 10:48:00
【问题描述】:

我正在准备在我的 Angular 应用程序中使用 SocketIoModule 将我的 Angular 应用程序与我的 NodejS 后端连接,但我在浏览器中遇到错误

我的后台

const express = require('express');
var cors = require('cors')
const app = express();

app.use(cors({
    origin: ':'
}))

const http = require('http');
const server = http.Server(app);

const socketIO = require('socket.io');
const io = socketIO(server);

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


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

io.on('connection', (socket) => {
    console.log('user connected');
    
});
io.on('new-message', (message) => {
    io.emit(message);
}); 

模块.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { SocketIoModule, SocketIoConfig } from 'ngx-socket-io';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { FormsModule } from '@angular/forms';
const config: SocketIoConfig = { url: 'http://localhost:3000', options: {} };

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    SocketIoModule.forRoot(config),
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

这会触发服务器上的“连接”事件,但会在浏览器控制台中引发错误

【问题讨论】:

  • 可能是一个愚蠢的问题,但您是否尝试过删除:app.use(cors({ origin: ':' }))
  • 如果有帮助,我想我可以收集一个旧的工作示例。
  • 无论有没有它,我都会遇到同样的错误。如果你发现它会很糟糕@JBoothUA
  • 好吧,它比较旧,如果我没记错的话,我使用 socket.io 和 Express Web 服务器将它连接起来,然后通过 IISNODE 将它连接到我的 IIS。不确定这是否相关,但我会发布它
  • 我实际上只是注意到了一些别的东西,所以我发布了一些代码和另一个理论:)

标签: node.js angular websocket socket.io cors


【解决方案1】:

我将按照承诺附上一些工作代码,但我可能刚刚注意到一些事情......错误消息提到端口 3000 和端口 4200,看起来你的套接字在端口 3000 上打开,所以我想知道是否你能查到 4200 是从哪里来的吗?


回复您的评论: 我相信 Socket.IO 用于连接 Client Server。所以你的配置可能有问题。您确定要使用不同的端口吗?正如您提到的,您想要 2 个服务器,但我猜您真的想要 1 个端口和 1 个服务器,运行 1 个具有客户端 服务器通信的应用程序?
无论如何,如果我不在那儿,可能只是因为端口/服务器不同,CORS 错误在这里实际上是有效的,您必须弄清楚如何将 CORS 标头添加到您的 Web 服务器:

例子:

xhr.setRequestHeader('Access-Control-Allow-Origin', '*');

将允许与任何客户进行通信


如果您想尝试比较代码,这是我建立的聊天室的一个较旧的工作示例。

app.js

var app = require('express')();
var http = require('http').Server(app);
var socket = require('socket.io')(http);

app.get('*', function(req, res){
    res.sendFile(__dirname + '/index.html');
});

socket.on('connection', function (io) {
    io.on('ioChatMessage', function (msg) {
        socket.emit('ioChatMessage', msg);
    });
});

http.listen(process.env.PORT);

index.html

<ul id="Messages"></ul>
<form action="">
    <input id="Message" autocomplete="off" />
    <input type="button" id="Send" value="Send" />
</form>


<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
    $.getScript('socket.io/socket.io.js', function () {
        initSocket();
    });

    var initSocket = function () {
        var socket = io();

        $('#Send').click(function () {
            var userNameTag = $('#UserNameTag');
            var nameTag = userNameTag.html();
            if (nameTag) {
                socket.emit('ioChatMessage', { text: nameTag + ':  ' + $('#Message').val(), style: userNameTag[0].style });
            } else {
                socket.emit('ioChatMessage', { text: $('#Message').val() });
            }

            $('#Message').val('');
            return false;
        });

        socket.on('ioChatMessage', function (msg) {
            $('#Messages').append($('<li>').text(msg.text).css(msg.style));
        });

        window.onbeforeunload = function () {
            socket.disconnect();
        };
    };
</script>
 

【讨论】:

  • 好像你有 2 个应用程序真的在运行?一个开发角度网络服务器和一个开发节点网络服务器。我认为您会希望节点服务器为 Angular 应用程序提供服务(在现实世界中),而开发 Angular Web 服务器仅用于独立测试 Angular 应用程序?
  • 是的@JBoothUA ,我有2个应用程序独立运行,我想要实现的是让它们在不使用同一个端口的情况下进行通信,假装它们在不同的服务器上,我在YouTube上看到了一些视频一切正常,我不知道会发生什么。
  • ClientServer 对不起,这就是我正在做的事情,但要做的是:(看我完全按照这个视频之前所说的做了,我得到了与 cors 块相同的结果@ JBoothUA
  • 我认为您需要将 Angular 应用程序加载到 HTML 文件中。只需将通过 ng build 创建的 js 文件加载到该 HTML 文件中,然后将 或类似的内容放入 HTML 正文中。然后通过您的 NODE Web 服务器提供该 HTML 文件(和您的 Angular 应用程序 js 文件)。这应该在 1 个端口上为您的 Angular 应用程序提供服务。然后,您应该能够通过 Web 浏览器(客户端)访问该端口并执行套接字通信
  • 这应该使您的 Angular 开发 Web 服务器端口脱离等式。我相信您现在正在运行 2 个单独的应用程序。您将希望在 1 个端口(用于服务器)上运行 1 个应用程序,然后您可以使用浏览器来表示客户端,但实际上它仍然是 1 个在 1 个端口上运行的应用程序
【解决方案2】:

解决办法:

我创建服务器

index.js

var express = require('express');
var socket = require('socket.io');
var port=3000;
// App setup
var app = express();
var server = app.listen(port, function(){
    console.log(`
    -------------Resume-------------------
    status:     listening
    port:       ${port}
    url:        http://localhost:${port}
    --------------------------------------`);
});

// Socket setup
var io = socket(server);

// Listen for new connection and print a message in console 
io.on('connection', (socket) => {

    console.log(`
    ------------New connection---------------------
    
    Connection ID:   ${socket.id}
    IP:              ${socket.handshake.address}
    Time:            ${socket.handshake.time}
    ----------------------------------------------`)

    // Listening for chat event
    socket.on('chat', function(data){
        
        io.sockets.emit('chat', data);
    });

    // Listening for typing event
    socket.on('typing', function(data){
        console.log('typing event');

        io.sockets.emit('typing', data);
    });

});

然后将 socket.io-client 和 **@types/socket.io-client ** 导入到我的 Angular 项目中 并创建一个 WebSocketService 来处理发射和监听器 并将服务添加到提供程序,并将 HttpClientModule 添加到 modules.ts 中的导入。

webSocketService.service.ts

import { Injectable } from "@angular/core";
import * as io from 'socket.io-client';
import { Observable } from "rxjs";

@Injectable()
export class WebSocketService {
    socket: SocketIOClient.Socket;

    constructor() {
        this.socket = io.connect('http://localhost:3000');
    }

    listen(eventname: string) : Observable<any> {
        return new Observable((subscriber) => {
            this.socket.on(eventname, (data) => {
                subscriber.next(data);
            })
        })
    }

    emit(eventname: string, data: any) {
        this.socket.emit(eventname, data);
    }
}

module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';

import { AppComponent } from './app.component';
import { WebSocketService } from './web-socket.service';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpClientModule,
  ],
  providers: [WebSocketService],
  bootstrap: [AppComponent]
})
export class AppModule { }

【讨论】:

    【解决方案3】:

    如果您使用的是 socket.io v.3.x,请查看此页面:https://socket.io/docs/v3/migrating-from-2-x-to-3-0/index.html,尤其是关于 CORS 处理的部分。

    您应该像这样实现您的应用程序:

    const io = require("socket.io")(httpServer, {
      cors: {
        origin: "https://example.com",
        methods: ["GET", "POST"],
        allowedHeaders: ["my-custom-header"],
        credentials: true
      }
    });

    还要确保您的 socket.io 版本匹配。

    【讨论】:

      猜你喜欢
      • 2017-07-24
      • 2017-01-22
      • 1970-01-01
      • 1970-01-01
      • 2022-01-06
      • 2018-06-12
      • 2021-12-01
      • 2013-11-30
      • 2020-03-31
      相关资源
      最近更新 更多