CORS issue on socket.io - javascript

I am trying to learn socket.io from this tutorial here. But the problem is I can't make the app run. This is the error I am getting:
XMLHttpRequest cannot load
http://127.0.0.1:3000/socket.io/?EIO=3&transport=polling&t=LZFI7Tq. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost' is therefore not allowed access.
The response had HTTP status code 404.
This is the server side connection
var io = require('socket.io');
var socket = io.listen(3000, '127.0.0.1');
// all the people that have joined the chat
var people = {};
socket.on('connection', function (client) {
console.log('An user connected');
client.on('join', function(name) {
people[client.id] = name;
// client.emit() will only update the client that you are looking
// at, whereas socket.sockets.emti() will update all connected clients
client.emit('update', 'You have successfully connected..');
socket.sockets.emit('update', name + " has joined the conversation..");
socket.sockets.emit('update-people', people);
});
client.on('send', function(msg){
socket.sockets.emit('chat', people[client.id], msg);
});
client.on('disconnect', function() {
socket.sockets.emit('update', people[client.id] + ' has left the conversation..');
delete people[client.id];
socket.sockets.emit('update-people', people);
});
});
And this is the client side connection
var socket = io.connect('http://127.0.0.1:3000');
I have gone through several posts related to this issue but cant solve it. Please help me.

Add this middle-ware on the server where your cookies are created
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept-Type');
res.header('Access-Control-Allow-Credentials', 'true');
next();
})

Related

I am trying to connection my HTML frontend to node js backend using sockets

I am trying to connect my html frontend to handle the socket.on event on my frontend. My nodejs server is running on 5858 port. And I am trying to run the socketio on same port but its not connecting. my nodejs code is below
const express = require('express');
const app = express();
const connectdb = require('./db/connect.js');
const port = process.env.PORT || 5858
const DATABASE_URL = "mongodb://localhost:27017";
const server = require('http').createServer(app);
const io = require('socket.io')(server , {
cors: {
origin: false,
withCredentials: false
}
}).listen(server);
//connection to database
connectdb(DATABASE_URL);
// apply to all requests
app.use(cors())
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
// app.use(express.limit('50M'));
app.use(bodyParser.json()) //Body Parser MiddleWare
app.use(express.json())
io.on('connection', (socket) => {
console.log("new connection")
socket.on('otpnumberevent', (data) => {
console.log(data);
let invid = data.id
invoicesModel.findOneAndUpdate(
invid,
data,
{
"fields" : {"otpverified" : 1},
"new": true
}
).exec((err , doc) =>{
console.log(doc)
if (err) {
let response = {
message: "Failed",
doc: err
}
io.emit('messageSent', response)
}
else {
let response = {
message: "Success",
doc: doc
}
io.emit('getotpresponse', response)
}
});
});
});
app.get('/' , (req , res) => {
res.send("Welcome to Dma backend");
});
server.listen(port, () => {
console.log('Server listening at port %d', port);
});
and from front end I am using the html code with .php extension so I am using the Online socket CDN to connect with socket my frontend code is here.
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.5.4/socket.io.js" integrity="sha512-YeeA/Qxn5hYdkukScTCNNOhTrv1C2RubAGButJ1rmgQwZf/HdRaCGl+JAVkqsqaNRaYNHdheiuKKuPf9mDcqKg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
var socket = io('http://localhost:5858', { transports: ['websocket', 'polling', 'flashsocket'] }); //socket connection code, my nodejs server is running on 5858 port
socket.on('getotpresponse' , (data) =>{
console.log(data);
if(data.doc.otpverified == "Yes"){
swal({
title: "Success!",
text: "Otp verification Successfull",
icon: "success",
button: "Okay!",
}).then(function() {
location.reload(true);
});
}else{
swal({
title: "Failed!",
text: "OTP verification failed!",
icon: "error",
button: "Okay!",
});
}
})
})
});
and whenever I try to connect from front end I get this error in my console screen.
I have tried everything. Added the CORS in the socket connection which can be seen in the above code. Still getting the same issue
Change cors -> origin to true
const io = require('socket.io')(server , {
cors: {
origin: true,
withCredentials: false
}
}).listen(server);
If it doesn't fix follow the following:
Check if the socket is connected to the same port as the nodejs server.
If the socket is connected to the same port as the node server, check if the CORS is enabled on the socket connection.
If the CORS is enabled, check if the headers are set correctly, such as origin, X-Requested-With, Content-Type, and Accept.
If the headers are set correctly, check if the socket is. The event is correctly configured on the front end.
If the socket. If it is correctly configured, could you please check if the invoice model.findOneAndUpdate function is correctly configured on the backend?
If the invoice model.findOneAndUpdate function is correctly configured, then check if the io. Emit function is configured on the backend.
If the io. Emit function is correctly configured, then check if the socket is. The event is correctly configured on the front end.
If the socket. If the event is correctly configured, could you please check if the swap function is configured on the front end?
Could you check the location of the swap function is correctly configured? Reload function is correctly configured on the front end.
If the location. Reload function is correctly configured, and then the issue should be resolved.

installing Socket.IO on NodeJs server

I would use Socket.IO . I have read the official documentation and tried to do the same thing so I create my server :
// server.js
// BASE SETUP
// =============================================================================
// call the packages we need
var express = require("express"); // call express
var app = express();
var bodyParser = require("body-parser");
// define our app using express
var routerProj = require("./routes/ajoutProj");
var mongoose = require("mongoose");
mongoose.Promise = global.Promise;
mongoose.connect("mongodb://localhost:27017", {
useMongoClient: true
/* other options */
}); // connect to our database
mongoose.connection.on("error", function(error) {
console.log("error", error);
});
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET, POST, PUT ,DELETE");
res.header(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Content-Type, Accept"
);
next();
});
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use("/api/proj", routerProj);
app.get("/", function(req, res) {
res.sendFile(__dirname + "../src/index.html");
});
// Chargement de socket.io
// Quand un client se connecte, on le note dans la console
io.sockets.on("connection", function(socket) {
console.log("User is coonected!");
});
var port = process.env.PORT || 8081; // set our port
// START THE SERVER
// =============================================================================
var server = app.listen(port);
var io = require("socket.io").listen(server);
My angular index.htlm file is in this path relatively to server.js : ../src/app/index.html
When I restart server and angular app, then open new window I don't have a message on the servers's console telling me that a user is connected knowing that angular is making calls to the server api
I don't know where is the problem
Update
I have added socket.IO on client side
import { Injectable } from "#angular/core";
import { NouveauProjet } from "./models/nouveau-projet";
import { HttpClient, HttpResponse } from "#angular/common/http";
import { Observable } from "rxjs/Observable";
import "rxjs/add/operator/map";
import "rxjs/add/operator/catch";
import * as io from "socket.io-client";
#Injectable()
export class AjoutprojService {
apiURL = "http://127.0.0.1:8080/api/proj/projets";
private socket = io("http://localhost:8081");
constructor(private http: HttpClient) {}
getAllProj(): Observable<NouveauProjet[]> {
return this.http.get<NouveauProjet[]>(
"http://127.0.0.1:8081/api/proj/projets"
);
}
getProj(id): Observable<NouveauProjet[]> {
return this.http.get<NouveauProjet[]>(
"http://127.0.0.1:8081/api/proj/nouvProjs/${id}"
);
}
addProj(nouveauProjet: NouveauProjet): Observable<any> {
return this.http.post<NouveauProjet[]>(
"http://127.0.0.1:8081/api/proj/projets",
nouveauProjet
);
}
}
/* private handleError ( response: HttpResponse): Observable<any> {
let errorMessage= `${response.status} - ${response.statusText}`;
return Observable.throw(errorMessage);
}*/
Restarted server , client , no result
Update 2
after adding socket.on('event', function(evt){ console.log(evt); });I get those errors :
Failed to load http://localhost:8081/socket.io/?EIO=3&transport=polling&t=M2tXQXh: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. Origin 'http://localhost:4200' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
GET http://localhost:8081/socket.io/?EIO=3&transport=polling&t=M2tXQXh 404 (Not Found)
If I set res.header("Access-Control-Allow-Origin", "*"); To res.header("Access-Control-Allow-Origin", "http://localhost:4200");
I get this error
Failed to load http://localhost:8081/socket.io/?EIO=3&transport=polling&t=M2uichH: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'. Origin 'http://localhost:4200' is therefore not allowed access. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
I notice a difference in the error . Here The value of the 'Access-Control-Allow-Credentials' header in the response is ''
When I put localhost:8081 : The value of the 'Access-Control-Allow-Credentials' header in the response is 'localhost:8081'
Based on the error, I suspect the problem is that you are using a wildcard in your server's CORS response header:
res.header("Access-Control-Allow-Origin", "*");
Why is this a problem? From the docs:
When responding to a credentialed request, the server must specify an origin in the value of the Access-Control-Allow-Origin header, instead of specifying the "*" wildcard.
Here is a relevant StackOverflow answer:
This is a part of security, you cannot do that. If you want to allow credentials then your Access-Control-Allow-Origin must not use *. You will have to specify the exact protocol + domain + port.

Missing Authorization header when send http request from browser

I have an application in nodejs with jwt authorization, when I send a get from posman the authentication header is found but when I send it from the browser, the authorization header is missing.
Here is the node code, I'm trying to get the authorization header in the verifyToken method, but is not there:
'use strict';
var SwaggerExpress = require('swagger-express-mw');
var app = require('express')();
module.exports = app; // for testing
var _ = require('lodash');
var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens
var config = {
appRoot: __dirname // required config
};
app.set('superSecret', config.secret); // secret variable
// bootstrap database connection and save it in express context
app.set("models", require("./api/model"));
var a = app.get("models").Role;
var repositoryFactory = require("./api/repository/RepositoryFactory").init(app);
var verifyToken = function (req, res, next) {
// verify token and read user from DB
// var token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiTm9tYnJlVXN1YXJpbyI6ImQiLCJQYXNzd29yZCI6IiQyYSQxMCRYS3BJM2ZDRVFoSzVKUFBQWEdIVVZPbUVPQTZsRVRoZDRtWHl4a0tDeGtUcEhvY0U0UTNILiIsImNyZWF0ZWRBdCI6IjIwMTYtMDktMDVUMTg6Mjk6MTYuMDAwWiIsInVwZGF0ZWRBdCI6IjIwMTYtMDktMDVUMTg6Mjk6MTYuMDAwWiIsInByb2Zlc2lvbmFsSWQiOm51bGwsInByb2Zlc2lvbmFsIjpudWxsLCJpYXQiOjE0NzMyNTczMjcsImV4cCI6MTQ3MzI5MzMyN30.CKB-GiuvwJsDAVnKsWb1FktI9tJY57lSgPRVEfW3pts';
var token = req.headers.authorization;
jwt.verify(token, 'shhhhh', function (err, decoded) {
if (err) {
res.status(403).json({ success: false, message: 'Failed to authenticate token.' });
} else {
// if everything is good, save to request for use in other routes
req.user = decoded;
next();
}
});
};
SwaggerExpress.create(config, function (err, swaggerExpress) {
if (err) { throw err; }
app.use(function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-CSRF-Token, X-Requested-With, Origin, client-security-token, X-Requested-With, Content-Type, Accept, Authorization");
res.setHeader('Content-Type', 'application/json');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
app.use(verifyToken);
// install middleware
swaggerExpress.register(app);
var port = process.env.PORT || 10010;
app.listen(port);
});
I don't know what configuration I'm missing.
The issue was that I was trying to get the authorization token from the OPTIONS method, this method is sent before the actual get, port, put etc, when is a CORS request. So I was trying to get the authorization header from it and it was not there and the method failed.
The solution was to set in the verify token method a validation like this:
if (req.method !== OPTIONS){
}
I think it is easier if you can change the code in verifyToken function : var token = req.headers.authorization; become var token = req.headers.authorization || req.query.access_token || req.body.access_token;
So in the browser, you can add token in "access_token" query param to authenticate in server instead of setting the header.
Hope it is helpful for you !
You need to set those headers in your browser, try use this chrome plugin called ModHeader https://chrome.google.com/webstore/detail/modheader/idgpnmonknjnojddfkpgkljpfnnfcklj
Try adding the following code in .htaccess. Apache removes the Authorization Header. This will ensure it is not removed.
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1

CORS Error: Angular.JS, Node.JS and Express [duplicate]

This question already has answers here:
Why doesn't adding CORS headers to an OPTIONS route allow browsers to access my API?
(36 answers)
Closed 7 years ago.
Having issues getting data back from a http post request to an API I've been building. Throws the error:
XMLHttpRequest cannot load (URL to API here). No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:9000' is therefore not allowed
access.
Here's the Angular code on the client side:
$http.post('MyAPIsURLHere', {
date: $scope.information.PubDate
})
.then(console.log)
.catch(console.error);
And here's the Node server side code for my API:
app.post('/getThing', (req, res) => {
const date = req.body.date;
const query = Overquery
const query2 = "alter session set nls_date_format = 'MM/dd/yyyy'";
oracleDB.execute(query2, (err, result) => {
if(err) {
console.error(err);
}
else {
console.log(result);
}
});
oracleDB.execute(query, (err, result) => {
if(err) {
console.error(err);
}
else {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'POST');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');
res.json(result.rows);
}
});
});
First time building an API so any suggestions and help would be greatly appreciated!
Run the following in your project from a bash shell:
npm install cors --save
It will install this:
https://github.com/expressjs/cors
Then add this to your server when creating the app.
var express = require('express');
var cors = require('cors');
var app = express();
app.use(cors());
Edit: This will enable CORS for every domain wich is not recomended for security reasons. Check here for further CORS configuration: https://github.com/expressjs/cors#configuring-cors
In your node application, this sample of code should solve your issues:
// Allowing X-domain request
var allowCrossDomain = function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Cache-Control");
// intercept OPTIONS method
if ('OPTIONS' == req.method) {
res.send(200);
}
else {
next();
}
};
app.use(allowCrossDomain);

Making CORS Request in Node.js/Express and AngularJS

I have seen many answers in stack overflow which says setting response headers will make you "CORS" request.But no solution worked for me.I have written the following code:
//Server.js Code
var express = require('express'),
app = express();
app.all('*',function(req, res, next) {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.setHeader('Access-Control-Allow-Credentials', true);
res.setHeader('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');
next();
I am trying to access the content from the URL using $http in client side:
//Controller.js
$http.get('http://domainA.com/a/ipadapi.php?id=135&client=ipad').success(function(response){
alert("I got response");
});
It's showing the following error in console.
XMLHttpRequest cannot load http://domainA.com/a/ipadapi.php?id=135&client=ipad The 'Access-Control-Allow-Origin' header has a value 'http://example.xxxxx.com' that is not equal to the supplied origin. Origin 'http://localhost:3000' is therefore not allowed access.
Note:I am new to nodeJS,Express and AngularJs
When you are passing credentials with CORS, you need to lock down the accepted origins. Try changing your origins from * to "localhost:3000"
See cross origin resource sharing with credentials
Change the header info from
res.setHeader("Access-Control-Allow-Origin", "*");
TO
res.header('Access-Control-Allow-Origin', 'http://localhost:3000');
If you're not the owner of domainA then you cannot send CORS headers from that domain. You can use your Node server as middleware, and proxy the request from your server to domainA. Your server can send CORS headers back to your angular app. pseudo code with hapi and needle:
import Hapi from 'hapi'
import needle from 'needle'
const server = new Hapi.Server()
server.connection({
port: 9090
, routes: {
cors: true
}
})
const handler = (req, reply) => {
const url = 'https://domainA.com'
, data = {
body: 'code'
}
needle.post(url, 'body=${data.body}', function(err, res) {
let json = JSON.parse(res.body)
reply(json.data)
})
}
server.route({
method: 'GET',
path: '/route/{id}',
handler: handler
}
)
server.start( err => {
if( err ) {
console.error( 'Error was handled!' )
console.error( err )
}
console.log( 'Server started at ${ server.info.uri }' )
})

Categories