Issue
Building an application with Angular and Node. Integrating a chat application built with Socket.io. Working fine when tested locally. Even after deploying the Node JS backend to the server machine (AWS EC2 Instance), Our local angular app can access the backend server. But after deploying the angular application in EC2, the chat module is not working and throwing an error " POST https://mysitedotcom/socket.io/?EIO=3&transport=polling&t=MzNa0m- 405 (Not Allowed) " Please find the server side code below.
require('./global_constants');
const Knex = require('knex');
const morgan = require('morgan');
const express = require('express');
const bodyParser = require('body-parser');
const promiseRouter = require('express-promise-router');
const rs = require('rocket-store');
const knexConfig = require('./knexfile');
const registerApi = require('./api');
const adminName = require('./config/config').admin.name;
const dbObj = require('./controllers/dbConn');
const cleaner = require('./controllers/textCleaner');
const fs = require('fs');
const rimraf = require('rimraf');
const socketIO = require('socket.io');
const db = dbObj.db;
const {
Model
} = require('objection');
const cors = require('cors');
const knex = Knex(knexConfig[process.env.NODE_ENV || 'production']);
Model.knex(knex);
const router = promiseRouter();
const app = express()
.use(bodyParser.json())
.use(morgan('dev'))
.use(cors(
{
credentials: true,
origin: ['http://localhost:4200', 'http://localhost:4201']
}
))
app.use('/api/', router).set('json spaces', 2);
app.use((req, res, next) => {
res.setHeader('Content-Type', 'application/json');
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
})
registerApi(router);
app.use((err, req, res, next) => {
if (err) {
console.error(err);
res.status(err.statusCode || err.status || 500).send(err || {});
} else {
next();
}
});
const http = require('https').createServer(app);
const io = socketIO(http);
http.listen(3000, function () {
console.log('listening on *:3000');
});
rs.options({
data_storage_area: "./msg",
data_format: rs._FORMAT_JSON,
});
io.on('connection', socket => {
socket.on('new-user', async (room, userId) => {
// some logic goes here
})
socket.on('new-message', async (room) => {
// Some logic
})
socket.on('user-disconnect', async (room, userId) => {
// Some logic
})
})
Please find the Client side code below
import { Injectable } from '@angular/core';
import * as io from 'socket.io-client';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ChatService {
private socket;
constructor() {
this.socket = io();
}
public newUser(roomName, id) {
this.socket.emit('new-user', id, roomName);
}
public userDisconnected(roomName,id){
this.socket.emit('user-disconnect',roomName,id)
}
public sendMessage(roomName, message,fullname,) {
this.socket.emit('new-message',roomName,message,fullname);
}
public getconnect = () =>{
return Observable.create((observer) => {
this.socket.on('user-connected', (message,prev,socketId,flag) => {
observer.next({msg:message,all_prev_msg:prev,socketId:socketId});
});
});
}
public getDisconnected = () =>{
return Observable.create((observer) => {
this.socket.on('user-disconnected', (message) => {
observer.next(message);
});
});
}
public getMessages = () => {
return Observable.create((observer) => {
this.socket.on('new-message', (room,message,userId) => {
observer.next({text:message,sender:userId});
});
});
}
}
Please let me know if anyone has any more questions. Many thanks.
Solution
Looks like you have nginx in your ec2 server, if yes you need to have the config below
location /static {
try_files $uri =404;
}
location /socket.io {
proxy_pass http://node;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
add_header Front-End-Https on;
}
error_page 405 @nodejs;
Answered By - AWS PS