Socket.io + Express CORS Error on localhost (not allowed by Access-Control-Allow-Origin) - node.js

I have a working node.js Express server to which I would to add socket.io support (allow javascript clients to connect via socket.io). I can connect to the express server via a Javascript $.get(), but the socket.io.connect() command fails due to a CORS error.
My testing machine is OSX with Apache to serve the client, thus port 80 is taken, so I have node.js/express running on port 8888. I added socket.io per the documentation:
var exp = express();
var server = require('http').createServer(api.server);
exp.listen(8888);
var io = require('socket.io').listen(server);
io.sockets.on('connection', function(socket) {
console.log('connection');
});
I properly see "info: socket.io started" in my node.js logs.
Then, on the client, I attempt to connect to the server...
this.socket = io.connect('http://localhost:8888');
this.socket.on('connect',function() {
socket.emit('install','test');
});
However, I'm getting a CORS error in the console in Chrome:
XMLHttpRequest cannot load http://localhost:8888/socket.io/1/?t=1358715637192. Origin http://localhost is not allowed by Access-Control-Allow-Origin.
HOWEVER, THIS works fine!
$.get('http://localhost:8888',function(e,d){
console.log(e,d);
});
So I double checked my headers, for both localhost:8888 and localhost -- both are properly returning the headers which (should) allow for the cross-domain requests...
Access-Control-Allow-Origin: *
Any ideas?

CORS is a very tricking thing to get working (or at least it was for me). I recommend this resource here: http://enable-cors.org/
Following what they do very carefully helped me. I also found that different browsers gave different visibility over the CORS request/responses which helped.
I found that Chrome was easier to get working than firefox, but firefoxes tools such as firebug, were quite nice to work with.
My gut feel from your information is that you might need your request to have an X-Request-With in your request attributes.
I also found using fidler to send the http requests allowed me to narrow my problems down to the server side initially and get that working. You will find browser enforce CORS, but something like fidler doesn't and thus provides another way of inspecting what is happening.
I definately recommend trying to break the problem in half so that you can see if it is server side or client side that is not behaving how you expect.
My problem was related to returning the same CORS response for the OPTIONS header as the POST or GET. That was wrong. Chrome allowed it. Firefox didnt. Any options request that is sent out will be sent out once, then in the future it will be cached and not resent (Which caused alot of confusion for me initially). For the options request you just need a standard response saying its ok to proceed, then in the post or get response i believe you want your cors responses there only.

Related

Socket IO allows CORS request from curl, but not from client application

I am making an application in which i have a node backend, and an angular frontend.
I am using socket.IO to communicate between my client and server.
I was facing CORS issue, which i solved (tried to) as:
const io: SocketIOServer = new SocketIOServer(server, {
cors: {
origin: true
}
}); // only for development
But still, upon making my request from my client app (running in another port) gives me CORS issue.
So i went to my terminal, and made a request with curl,as shown here:
me#Desktop:~$ curl "http://127.0.0.1:5000/socket.io/?EIO=4&transport=polling&t=NV5sBAn"
0{"sid":"jAhPIEEkdy8EY8I_AAAD","upgrades":["websocket"],"pingInterval":25000,"pingTimeout":5000}
This suggests me that curl is being able to access the server, and is not facing CORS issue.
In my client, i am trying to connect to my server as:
socket = io.connect('http://locahost:5000'); // server running at port 5000
Help me with my issue, so i can connect with my server.
Also on a sidenote: If the version of server.io in the app is 3, the curl request to the server is also failing. only upon server.io version 4, the curl request is passing.
The error in firefox if that helps:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://locahost:5000/socket.io/?EIO=4&transport=polling&t=NV5vi1_. (Reason: CORS request did not succeed).
EDIT: my issue is not being able to connect to the server with client. I showed the curl because it was suggested in the socket.io cors configuration webpage.
Because socket.io initiates its connection with plain http requests, it is subject to CORs restrictions. CURL does not enforce CORs restrictions (like the browser does) so that's why you don't see it there.
You have a couple options:
You can enable this specific CORs request in your server to permit it.
You can specify the {transports: ['websocket']} option for your socket.io connection in the socket.io client code that initiates the connection. This will tell socket.io to immediately start with a webSocket connection which is not subject to CORs.
Curl does not implement CORS security restrictions, thus it will always be able to connect. You have different ports for your frontend and backend which are considered different CORS origins. So you either need to set your allowed origins correctly on your server and make sure it handles the pre-flight requests, or have the process serving your frontend proxy requests to the backend so that everything is on the same url from the browser’s point of view
Apprrently, the issue was:
socket = io.connect('http://localhost:5000');
changing this to:
socket = io.connect('http://127.0.0.1:5000');
worked!! I have no idea why this name was not getting resolved!!

"Cross Origin Request Blocked" No solutions seem to work

Background
I'm building a MERN full stack application as a personal project. I am running the frontend client on localhost:3000 and the server on localhost:5000.
Problem
All of my API routes work as expected except for a GET request, router.get('/get-friends', ...) which queries the mongoDB to return a list of collection documents. Calling that get request on Postman returns the expected output. I decided to write a simple GET request that returns a method and it works just fine in my browser
When making the request the get-friends request in my browser, I get the following log:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:5000/api/users/get-friends/. (Reason: CORS request did not succeed)
What I've Already Tried
Enabling cors in my Express server
Enabling cors preflight
Adding a proxy to the server from the client's package.json
Switching from Axios to vanilla JS's fetch() method
Turning off cors in my browser
I suspect the issue occurs when I make the request to the database from Express. I am really not sure how to solve this issue.
Here is the route in question:
router.get('/get-friends', (req, res) =>{
var species_ = req.body.species;
var gender_ = req.body.gender;
var neutered_ = req.body.neutered;
// query db
Friend.find({species: species_},{gender:gender_},{neutered:neutered_}).then((friends_) =>{
if(!friends_){
return res.status(404).send('query error, nothing returned');
}
return res.send(friends_);
}).catch((e) =>{
res.status(400).send(4);
})
});
Here is the project repo and the relevant files are:
https://github.com/edgarvi/foster-friends/server.js (Express server)
https://github.com/EdgarVi/foster-friends/blob/master/routes/api/users.js (Routes for the express server)
https://github.com/EdgarVi/foster-friends/blob/master/client/src/components/layout/SearchFriends.js (React component which calls the server)
I would gladly appreciate any help!
I have highlighted possible problems.
Reason: CORS request did not succeed
The HTTP request which makes use of CORS failed because the HTTP
connection failed at either the network or protocol level. The error
is not directly related to CORS, but is a fundamental network error of
some kind.
> In many cases, it is caused by a browser plugin (e.g. an ad blocker or
privacy protector) blocking the request.
Other possible causes include:
Trying to access an https resource that has an invalid certificate
will cause this error.
Trying to access an http resource from a page with an https origin
will also cause this error.
As of Firefox 68, https pages are not permitted to access
http://localhost, although this may be changed by Bug 1488740.
> The server did not respond to the actual request (even if it responded
to the Preflight request). One scenario might be an HTTP service being
developed that panicked without returning any data.
https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSDidNotSucceed
Thank you all for the help and the suggestions. After struggling through this for multiple days, I finally encountered a solution.
In my react client, I made the API call:
axios.get('http://localhost:5000/api/users/get-friends',
{
params: {
species: this.state.species,
gender: this.state.gender,
neutured: neutered_
}}
);
and then I changed the Mongoose query to look like:
router.get('/get-friends', (req, res) =>{
var species_ = req.query.species;
var gender_ = req.query.gender;
var neutered_ = req.query.neutered;
// query db
Friend.find({species: species_},{gender:gender_},{neutered:neutered_}).then((_friends) => {
return res.send(_friends);
})
});
I'm not exactly sure why these changes made my code finally work but once again, thank you all for the help and suggestions!

Problems connecting front-end app with the server

I have an Angular app running in gh-pages https://yourweatherapp.github.io/yourweatherapp.github.io which make requests to a node.js app that it´s running in a host.
Previously, I have consulted other info on the net like this How to allow CORS?, but solutions don´t work for me
I have configured the node.js app to allow request from this origin on this way:
const corsMiddleware = cors({
origin: [process.env.URL, 'https://yourweatherapp.github.io/yourweatherapp.github.io/login']
})
app.use(corsMiddleware)
app.options('*', corsMiddleware)
But the browser doesn´t allow to receive the answer and do login.
What am I doing wrong?
'https://yourweatherapp.github.io/yourweatherapp.github.io/login'
Look at the error message in the browser console. It will tell you the origin that doesn't have permission to read the data, and it won't be that.
Origins do not include paths. So that is not a valid origin.
It should be only https://yourweatherapp.github.io

Sending a cookie to web browser using Node.js Express

I am following all the suggestions online about how to send a cookie in an HTTP response in Express.
The simple way would be like so:
app.use(function(req,res,next){
res.cookie('foo', 'bar');
});
however when future requests come to the server from the same web browser, the cookie is not available in req.cookies; in other words, req.cookies['foo'] is undefined.
I have set the front-end code to use "withCredentials" for any AJAX request. Yet the cookie is still not sent to the server, or at least does not appear to be in any way.
One thing that concerns me is that when I call res.cookie('foo','bar') on the server it doesn't show up on the res object/stream as you can see here:
https://www.dropbox.com/s/fe317re9g2frucv/Screenshot%202016-01-21%2023.49.45.png?dl=0
Is there anything obvious that I am doing wrong?

Socket.IO issue with illegal origin?

I am using :
"socket.io": "~0.9.10"
I am running into this issue when I go to my apache webserver hosted client.html page hosted on port 80:
XMLHttpRequest cannot load http://localhost:5000/socket.io/1/?t=1348624895534. Origin http://localhost is not allowed by Access-Control-Allow-Origin.
I am running SocketIO on my serverside to be on port 5000 as shown below:
io = io.listen(5000);
io.set("origins","*");
However, everytime I load my apache client.html page, I see in my SocketIO server console:
warn: illegal origin: http://localhost
How do I get rid of this issue?
You are doing CORS.
The error you are getting comes from the fact that Socket.IO seems to be using XHR rather that Websockets. This is what socket.IO does when websockets are not available it uses another protocol, FlashSockets, XHR-polling... etc.
You need to set a header on you apache server to allow a query to be made to another website, here your Socket.io server.
Here is a how to.
It would be a lot simpler for you if you just used only one server.
You could use Express to deliver the static html file. Here is a demo/tutorial app to get started easily with Socket.IO + Express.
This demo is a boiler plate to push on dotCloud, so if you want to painlessly deploy, follow those instructions.
Try setting 'Access-Control-Allow-Origin' header to '*'
response.writeHead(200, {
'Access-Control-Allow-Origin': '*'
});

Resources