Cannot connect to socket.io server: Cross-origin request blocked - node.js

This is a nodejs server:
var express = require('express');
var app = express();
app.use(express.static('public'));
const server = require('http').createServer(app);
server.listen(1437, function(){
console.log('https and websocket listening on *:1437');
});
The client is:
var socketOptions = {
secure: true,
reconnection: true,
reconnectionDelay: 1000,
timeout: 15000,
pingTimeout: 15000,
pingInterval: 45000,
query: {
framespersecond: frameRate,
audioBitrate: audioRate
}
};
socket = io.connect('https://localhost:1437', socketOptions);
After I run node server.js I check that the server correctly starts.
But when I run the page where the client is, this error is shown in developer console:
Cross-origin request blocked: The same origin policy does not allow reading of remote resources at https://localhost:1437/socket.io/?Framespersecond=15&audioBitrate=22050&EIO=3&transport=polling&t=NJDLua7. (Reason: CORS request not successful)
How can I solve it? currently, this is my development machine. When I deploy the web page in production, will I just need to change localhost by the remote server name?
This is package.json of the server:
{
"name": "rtc2rtmp",
"version": "1.0.0",
"description": "mediarecorder -> websocket -> rtmp",
"dependencies": {
"express": "^4.17.1",
"fluent-ffmpeg": "^2.1.2",
"socket.io": "^2.3.0"
}
}
And nodejs version is 14.12.0

The cross origin issue is caused by socket.io's attempt to first connect on regular http before it tries to make a webSocket connection. You can tell it to just go directly to the webSocket connection which is not subject to the cross origin restrictions by adding this:
transports: ['websocket']
to your client-side socket options and you will avoid the cross origin issue entirely since webSocket connections are not subject to cross origin restrictions.
The other alternative it to enable cross origin requests from this origin on your express server, but if you don't really need the non-webSocket transport support, then just telling the client to start out directly with a webSocket connection is easier.

Related

localtunnel and CORS not working properly

I am using localtunnel to expose my backend and frontend. Right now, I have a very simple setup like this one:
const httpServer = require('http').createServer();
const socketIO = require('socket.io');
const io = socketIO(httpServer, { cors: { origin: '*' } });
io.on('connection', (socket) => {
...
});
httpServer.listen(5000, () => {
console.log(`Listening on the port 5000`);
});
I then expose this backend with localtunnel with lt --port 5000. I then get the URL, set it up in my React frontend, start the frontend app running on port 3000 and then lt --port 3000. Then, when I try to connect to the backend, I keep getting this error.
Access to XMLHttpRequest at 'https://tame-mayfly-63.loca.lt/socket.io/?EIO=4&transport=polling&t=NbU6WbU' from origin 'https://spotty-robin-42.loca.lt' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
First I thought this was some error with localtunnel, but then tried with ngrok and the error is the same. I am enabling all origins from CORS, so I don't know what might be happening.
Doing curl "https://tame-mayfly-63.loca.lt/socket.io/?EIO=4&transport=polling" works, but I guess that's because CORS is ignored when making the request with cURL.
I found the solution for my problem. Looks like you first need to access to the dynamic url serving your backend and click on "Continue". After doing that, CORS won't be a problem anymore.

How can I deploy a Node HTTP/2 server to Google App Engine?

I have a regular Node(v12) http server on App Engine. I switched to http2 with http2.createSecureServer. It works in development, but deploying to App Engine and after the server starts successfully it responds to requests with 502 bad gateway...
I tried to switch to http2.createServer to not use https, and the request never receives a response (forever loading). The last log in App Engine Log Explorer for that request shows:
[error] 27#27: *2 upstream sent no valid HTTP/1.0 header
while reading response header from upstream, client:
169.254.1.1, server: _, request: "GET / HTTP/1.1",
upstream: "http://127.0.0.1:8081/"
It seems like it somehow is expecting http1, but I don't know why. I also don't know why it's on port 8081, I have the port set to 8080.
After spending my day searching Google and their docs for anything on using http2 with App Engine, I'm burnt out. And, their support page says "post on Stack Overflow"..
main.js
const http2 = require('http2');
const fs = require('fs');
const app = new (require('koa'))();
const logger = require('koa-logger');
const bodyParser = require('koa-bodyparser');
const json = require('koa-json');
const cors = require('#koa/cors');
const router = require('./router.js');
const { PORT, HOST, KEY, CERT } = require('./config.js');
app.use(logger());
app.use(bodyParser());
app.use(json());
app.use(cors({ exposeHeaders: 'authorization' }));
app.use(router.routes());
app.use(router.allowedMethods());
const server = http2
.createSecureServer(
{
key: fs.readFileSync(KEY),
cert: fs.readFileSync(CERT),
allowHTTP1: true
},
app.callback()
)
.listen(PORT, () => {
console.log(`Koa HTTP/2 running at https://${HOST}:${PORT}`);
});
app.yaml
runtime: nodejs12
service: api
handlers:
- url: /.*
script: auto
secure: always
redirect_http_response_code: 301
vpc_access_connector:
name:
env_variables:
NODE_ENV: production
PORT:8080
KEY: key.pem
CERT: cert.pem
...
If you want to use HTTP/2 and App Engine together you might consider using Load Balancing with your serverless applications. A 502 Error in Google App Engine might refer to several different possibilities.
Error message BAD_GATEWAY
An error code 502 with BAD_GATEWAY in the message usually indicates that App Engine terminated the application because it ran out of memory. The default App Engine flexible VM only has 1GB of memory, with only 600MB available for the application container.
Error code 502 or 503
App Engine may take a few minutes to respond successfully to requests. If you send a request and get back an HTTP 502, 503, or some other server error, wait a minute and try the request again.

Connect node.js PostgreSQL database and Vue client locally

New to all of this so this might be the wrong setup. I have set up one project which uses node to connect to a postgreSQL. This works and I can start this from VS Code using:
node index.js
and the response is:
App running on port 3000.
Another project is a client and has been created Vue. This is started using
npm run serve
The response is:
App running at:
- Local: http://localhost:8080/
The Vue client gets data from a source using the code below and then displays it. In this example it uses some dummy data and works fine.
created: function () {
axios
.get('https://jsonplaceholder.typicode.com/users/')
.then(res => {
this.users = res.data;
})
}
However if I change the source above to communicate with the local postgreSQL database server:
.get('http://localhost:3000/users/')
I quite rightly get the security issue in the browser console when trying to connect:
Cross-Origin Request Blocked: The Same Origin Policy disallows reading
the remote resource at http://localhost:3000/users/. (Reason: CORS
header 'Access-Control-Allow-Origin' missing)
So how do I intergrate the node.js part and the vue client part?
UPDATE
The answer to the question is below but I changed very slightly. The following was added to the index.js file (the node postgreSQL part). It is importing cors and saying allow conneciton from localhost:8080. Works perfectly:
import cors from 'cors';
const corsOptions = {
origin: 'http://localhost:8080'
};
You have to install lib cors. For that in your project folder just run the command:
npm i --save cors
After that lib is installed you should import and configure in your server application. To enable your front-end communicate with server side application.
const express = require('express');
const logger = require('morgan');
const cors = require('cors'); //<--install this lib
const app = express();
cors({ credentials: true, origin: true });//enable some headers for handling authentication tokens
app.use(cors());//use in your server
app.use(express.json());
if (process.env.NODE_ENV !== 'test') { app.use(logger('dev')); }
app.use(require('./server/index'));
module.exports = app;
As stated by the documentation, when you use the function cors() its equivallent to:
{
"origin": "*",
"methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
"preflightContinue": false,
"optionsSuccessStatus": 204
}

React, proxy to websocket from package.json get local machine

On AWS ec2 instance I have 2 projects react and nodejs
Due to specific of server I can't connect toc socket by it's ip, but...
I'm trying to use localhost from react package.json proxy, but it's not working. React trying to get :3334 port on my local machine
"proxy": {
"/api": {
"target": "http://localhost:3000"
},
"/socket.io": {
"target": "http://localhost:3334",
"ws": true
}
}
React on port 8000, nodejs on port 3000, socket should be listened on port 3334. I implement connection to nodejs, but with this ws. Can't understand what an I doing wrong
in react:
const socket = openSocket("http://localhost:3334");
On other instance or local machine everything works fine, with ip, but I really need this localhost connection.
Please, help
The problem was that I define in react io socket strictly to localhost. Solution:
const socket = openSocket();

Socket.io Letsencrypt and a secure connection failing on CORS

I have a simple node.js setup running socket.io >1.0.0;
fs = require('/home/node/bin/node_modules/file-system');
// Options for socket.io > 1.0.0
var options = {
allowUpgrades: true,
transports: [ 'polling', 'websocket' ],
pingTimeout: 6000,
pingInterval: 3000,
cookie: 'nom-nom',
httpCompression: true,
key: fs.readFileSync('/etc/letsencrypt/live/example.com/privkey.pem'),
cert: fs.readFileSync('/etc/letsencrypt/live/example.com/fullchain.pem'),
origins: '*:*'
};
io = require('/home/node/bin/node_modules/socket.io')(8000, options);
When a client connects from a page served via http they are able to connect as expected and the socket connection is allowed. If a client tries to connect from a page served over https I get the following error;
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://example.com:8000/socket.io/?EIO=3&transport=polling&t=MfVDWxD. (Reason: CORS request did not succeed).
Given my CORS policy is already set for *:* which should allow anything I don't understand why it's failing.
I have tried adding {secure: true} to the client connection, and I've also tried forcing a wss:// and https:// url for the connection string - all result in the same CORS error.
This is a bare socket implementation, not using any framework like express or even http.
Can someone point me in the right direction so that I can allow my clients to connect via https or ideally http and https.
you need to install cors, you can do that with npm or any other package manager
then in your nodejs app:
// require cors
const cors = require("cors");
// Use Cors As Middleware
app.use(cors());

Resources