0
votes

I am able to access other endpoints from my frontend but when I want to access the socket endpoint I get this error message:

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

chatapp.component.ts

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { User } from '../models/users';
import { AuthService } from '../services/auth.service';
import { SocketService } from '../services/socket/socket.service';
import { UsersService } from '../services/users/users.service';

@Component({
  selector: 'app-chatapp',
  templateUrl: './chatapp.component.html',
  styleUrls: ['./chatapp.component.scss']
})
export class ChatappComponent implements OnInit {

  private socket
  chatForm:FormGroup
  user:User
  groups
  submitted =false
  constructor(
    private socketService:SocketService,
    private formBuilder:FormBuilder,
    private userService:UsersService,private authentication:AuthService) {
      this.chat()
    }

  ngOnInit(): void {
    this.getUser()
    this.getUserGroups()
  }

  chat(){
    this.chatForm = this.formBuilder.group({
      chat:['',Validators.required]
    })
  }
} 

socket.service.ts

import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { catchError, retry } from 'rxjs/operators';
import * as io from 'socket.io-client';


@Injectable({
  providedIn: 'root'
})
export class SocketService {

  private socket
  private socketUrl = 'http://localhost:3000';

  constructor(private http: HttpClient) {
    this.socket = io(this.socketUrl)
  }
}

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { LoginComponent } from './login/login.component';
import { SignupComponent } from './signup/signup.component';
import { ChatappComponent } from './chatapp/chatapp.component';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { SocketService } from './services/socket/socket.service';

@NgModule({
  declarations: [
    AppComponent,
    LoginComponent,
    SignupComponent,
    ChatappComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    FormsModule,
    ReactiveFormsModule,
    HttpClientModule
  ],
  providers: [SocketService],
  bootstrap: [AppComponent]
})
export class AppModule { }

my backend server app.js

const express = require('express')
const http = require('http')
const path = require('path')
const socketIO = require('socket.io')
const moment = require('moment')
const morgan = require('morgan')
const winston = require('winston')
const formateMessage = require('./utils/messages')
const formatMessage = require('./utils/messages')
const cors = require('cors')

const app = express()
app.use(morgan('tiny'))
app.use(cors())
require('./startup/db')()
require('./startup/router')(app)
app.get('',(req,res) => {
    res.send({
        title:'Chat-App',
    })
});

const server = http.createServer(app)
const io = socketIO(server)

//Set static folder
app.use(express.static(path.join(__dirname,'public')));

const appName = "Chat-app"

io.on('connection',socket => {
    socket.on('joinRoom', ({username , room }) => {

        //to the single client connecting
        socket.emit('message',formateMessage(appName,'Welcome to chat-app!'));

        //Broadcast when a user connected to all users except that particular user that connected
        socket.broadcast.emit('message',formateMessage(appName,'A user has joined the chat'));

        //when client disconnet
        socket.on('disconnect', () => {
            io.emit('message',formatMessage(appName,'A user has left the chat'))
        })
    })

    //to all the clients in general
    //io.emit()

    //listen to chat message
    socket.on('chatMessage', msg => {
        io.emit('message',formatMessage('user',msg))
    })

})




server.listen(3000,() => {
    winston.info("----Project is up and running----")
});
2

2 Answers

1
votes

Since your angular is running on 4200 port and backend running on 3000 port, the origin of both the application is different. For security reasons, it's shown as we are in the development mode of angular.

Basically, by run (Win + r) the following command (or creating a shortcut with it and opening Chrome through that)

chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security

You can open a new "insecure" instance of Chrome at the same time as you keep your other "secure" browser instances open and working as normal.

The error will be resolved in the production mode of the project.

-1
votes

There are two ways you can achieve this

1)By disabling web security in browser using

chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security

2)By adding proxy to angular code.You can find detailed steps here

{
        "/api": {
            "target": "http://localhost:3000",
            "secure": false
        }
    }