webRTC connection working when connecting to webpage hosted locally, but not when hosted on a server - express

I am attempting to create a webRTC connection from a python app to a web service using aiortc on python side, and express js on the web service side. When hosting the web service on localhost I have no problems, however when I host it on a server I am unable. I can still access the web page just fine when hosted online, I just get the following very generic exception when I attempt to make a webRTC connection:
socketio.exceptions.ConnectionError: Connection refused by the server.
Here is what I think is the relevant part of the python code:
import asyncio
import dataclasses
import os
import socketio
from pathlib import Path
from aiortc import RTCPeerConnection, RTCSessionDescription
from data_streams.StreamingTrack import StreamingTrack
# Socket.io details
NODEJS_URL = 'something.something.nl'
NODEJS_PORT = '4000'
ROOT = os.path.dirname(__file__)
CLASSROOM_ID = "defaultClassroom"
sio = socketio.AsyncClient()
await sio.connect("http://" + NODEJS_URL + ":" + NODEJS_PORT)
And here is what I believe is the relevant js code:
const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users');
const app = express();
app.options('*', cors());
app.set('port', (process.env.PORT || 8080));
// initiating the socket server
const port = 4000;
const server = http.createServer(app);
const io = require('socket.io')(server);
app.use(express.static(__dirname + '/public'));
io.sockets.on('error', (e) => console.log(e));
io.sockets.on('connect_error', (err) => {
console.log(`connect_error due to ${err.message}`);
});
If any additional code is needed I can provide it.
The firewalls have been disabled so I don't think that is the issue, I would greatly appreciate any suggestions as to why I am unable to connect.

Related

socketIO over SSL on Smartphone Browser

I have an Apache webserver with a valid SSL certificate. It runs my web application on it. Let's call it Server A.
Then I have a second server running a Node-Js server with a valid SSL certificate. There also socket.IO runs. And this one we call Server B.
A client requests the web application at server A and gets the desired page displayed. If the page is set up at the client, a connection to server B is established via websockets. If another client should change something on the page, it will be adapted for all currently connected clients.
Websockets work as desired. As long as the page is accessed via a computer browser.
If I now go to the website with my smartphone (Iphone 7) via Safari or Chrome (WLAN), no connection to the websocket server (Server B) is established.
Then I set up a small websocket example on http without encryption.
There the websockets work on the smartphone browser.
I hope I could describe my problem understandably. I am very grateful for hints, examples or similar.
// This script run on my Server
const fs = require('fs');
const server = require('https').createServer({
key: fs.readFileSync('myserver.key', 'utf8'),
cert: fs.readFileSync('myserver.cer', 'utf8'),
passphrase: ''
});
let io = require('socket.io')(server);
server.listen(3003);
io.on('connection', function (socket) {
console.log("User Connected connect " + socket.id);
socket.on('disconnect', function () {
console.log("User has close the browser " + socket.id);
});
socket.on('feedback', function (data) {
io.sockets.emit('feedback', data);
});
});
// On Clientsite
socket = io.connect('wss://adressOfServer:3003', {
// secure: true,
transports: ['websocket'],
upgrade: false,
rejectUnauthorized: false
//Here I have already tried many combinations
});
socket.on('connect_error', function (error) {
// alert(error);
});

Feathers errors on a client side

My stack react/redux/redux-observable/immutablejs.
Client is rendered by feathers.js using server side rendering.
I use feather-client, after getting 400 (Request doesn't pass validation).
I've got a response in .json format. But for some reasons it's converted to HTML or string.
Error: Order validation failed
at BadRequest.ExtendableBuiltin (bundle.js:106696)
at BadRequest.FeathersError (bundle.js:106771)
at new BadRequest (bundle.js:106812)
at convert (bundle.js:107040)
at toError (bundle.js:106043)
Any ideas how to disable it on a client?
import 'isomorphic-fetch';
import feathers from 'feathers-client';
import authentication from 'feathers-authentication-client';
import config from './config';
let storage = null;
if (!process.env.BROWSER && process.NODE_ENV !== 'test') {
require('localstorage-polyfill');
storage = global.localStorage;
}else{
storage = window.localStorage;
}
const port = process.env.PORT || config.port;
promise.polyfill();
const rest = feathers.rest(`http://localhost:${port}/api`);
const app = feathers()
.configure(feathers.hooks())
.configure(rest.fetch(require('isomorphic-fetch')))
.configure(authentication({ storage }));
export default app;
Spend some minutes fixing it, it's simply implement .toJSON() method...

socket.io.js not found (404)

I am referring to an issue that has been asked many times but the solutions posted elsewhere are not resolving my problem ie socket.io.js not found.
The error message is
GET http://127.0.0.1:3000/socket.io/socket.io.js 404
Any help would be appreciated.
I referenced socket.io.js in my JADE file:
script(src='http://code.jquery.com/jquery.js')
script(src='http://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js')
script(src='/socket.io/socket.io.js')
script(src='/javascripts/sockets/client.js') // this is in public folder
In my App.js file:
var express = require('express');
io = require('socket.io');
http = require('http');
app = express();
server = http.createServer(app);
io = io.listen(server);
server.listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
app.use(express.static(path.join(__dirname, 'public')));
These are the versions I am using:
"express": "~4.13.1",
"jade": "~1.11.0",
"morgan": "~1.6.1",
"serve-favicon": "~2.3.0",
"socket.io": "0.9.10"
Some additional info:
In my app.js: I referenced the server socket
// set up our socket server
require('./public/javascripts/sockets/server')(io);
'/javascripts/sockets/client.js' is my client socket:
var socket = io.connect('/');
socket.on('message', function (data) {
data = JSON.parse(data);
$('#messages').append('<div class="'+data.type+'">' + data.message +
'</div>');
});
$(function(){
$('#send').click(function(){
var data = {
message: $('#message').val(),
type:'userMessage'
};
socket.send(JSON.stringify(data));
$('#message').val('');
});
You shouldn't be using the socket.io package for this as it is primarily intended to construct a socket.io server instance. Instead you should be using socket.io-client which was specifically made to be used as the client socket.
I would recommend using bower to install this instead of npm as bower is made for front-end package management. Inside your project directory execute the following
note: If you don't have bower installed you'll need to install it globally npm i -g bower
bower init
bower install --save socket.io-client
Then you should make the bower_components directory created by installing the socket.io-client a static directory
server.use(express.static(path.join(__dirname, 'bower_components')));
Then change
script(src='/javascripts/sockets/client.js') // this is in public folder
to
script(src='/bower_components/socket.io-client)
Additionally, you're mixing your server and app variables. You should be using whatever variable your socket.io was created using, in this case you're using server so you should be using that. Your server file is mostly incorrect as you're instantiating many global values and you've created your io instance incorrectly.
var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var port = process.env.PORT || 3000;
server.use(express.static(path.join(__dirname, 'public')));
server.use(express.static(path.join(__dirname, 'bower_components')));
server.listen(port, function(){
console.log('Express server listening on port ' + port);
});

Node express server, CORS API restriction, including an entry in my development machine’s hosts file

I am trying to use an API that has an API CORS policy that does not support browser requests from any domain. In order to allow clientside JavaScript code to access the API, whilst developing my application, I have been advised to I serve my webapp from '*.thisCompany.com' domain.
It was advised to include an entry in my development machine’s hosts file, as follows, which I have done:
$ echo '127.0.0.1 localhost.thisCompany.com' >> /etc/hosts
Following this command when I run sudo nano /private/etc/hosts
this is the screen that I see.
Host Database
localhost is used to configure the loopback interface
when the system is booting. Do not change this entry.
127.0.0.1 localhost
127.0.0.1 localhost.thisCompany.com
And then I have been told that I should be able access my webapp at http://localhost.thisCompany.com.
I am using node express as my server and the code in my server.js file looks like this
var express = require('express');
var server = express();
var path = require('path');
var port = process.env.PORT || 'thisCompany.com';
server.use(express.static(__dirname + '/public'));
server.use('/bower_components', express.static(__dirname + '/bower_components'));
server.get('/', function(request, response) {
response.sendFile(path.join(__dirname + '/views/index.html'));
});
server.listen(port, function() {
console.log("Node app is running at localhost:" + port)
});
Can anyone advise what steps I should follow to enable me to call this API and bypass the API CORS policy?
I have read various other posts here, and also other articles online, however I cannot find the solution. Really hoping someone on this can help.
Thanks, Paul
I misunderstood how I was supposed to view a page locally on my computer after amending the hosts file on my local machine. I didn't need to add anything to my express server. The express server code remained as follows:
var express = require('express');
var server = express();
var path = require('path');
var port = process.env.PORT || 3000;
server.use(express.static(__dirname + '/public'));
server.use('/bower_components', express.static(__dirname + '/bower_components'));
server.get('/', function(request, response) {
response.sendFile(path.join(__dirname + '/views/index.html'));
});
server.listen(port, function() {
console.log("Node app is running at localhost:" + port)
});
After adding the line mentioned in my original post to my hosts file on my local machine, I then needed to launch my server and access the page by following this link.
http://localhost.thisCompany.com:3000/
Although this is quite a niche issue, I hope this post helps someone in the future.

Using https on heroku

I'm trying to get my app on heroku to be 'https everywhere'. So far the app is like this:
"use strict";
console.log('working');
//Initial setup
var path, https, privateKey, certificate, port, cdjshelp, util, cookies, oauth, twitter, crypto, _, options, express, auth, lodash, dust, dustjs,
dustjsHelpers, commonDustjsHelpers, app, db, fs, mongoose, mongooseTimes, Comment, Bird, Sighting, Site, User,
Backbone, io;
//node modules, express and dust declarations
path = require('path');
util = require('util');
fs = require('fs');
https = require('https');
privateKey = fs.readFileSync('./config/privatekey.pem').toString();
certificate = fs.readFileSync('./config/certificate.pem').toString();
crypto = require('crypto');
//APP Defn...
app = require('./config/appSetup')(dustjs);
//******** SERVER CONFIG **********//
var port = process.env['PORT'] = process.env.PORT || 4000; // Used by https on localhost
options = {
key: privateKey,
cert: certificate
}
https.createServer(options, app).listen(port, function() {
console.log("Express server listening with https on port %d in %s mode", this.address().port, app.settings.env);
});
I've used the openSSL CLI to generate a privatekey.pem and a certificate.pem and loaded them as options.
I know that heroku has a procedure if you're using DNS records to have the app serve to your own domain. I know that you have to go through the procedure listed here. I'm not remapping any urls or altering any records - my url is birdsapp.heroku.com.
Heroku uses piggyback SSL, so if you setup an http server your app will respond to https requests without any additional config. The problem there is that the http routes are still available, so I've stuck to setting an https server only - but it's timing out with nothing in the logs, so I think that there's a problem with the SSL setup.
Is the above setup correct? Is that the best way to do basic https server on heroku?
OK, it's actually much simpler than that...
You simply create an http server:
//******** SERVER CONFIG **********//
var port = process.env['PORT'] = process.env.PORT || 4000;
http.createServer(app).listen(port, function() {
console.log("Express server listening with http on port %d in %s mode", this.address().port, app.settings.env);
});
and add a route redirect:
app.all('*', function(req, res, next) {
if (req.headers['x-forwarded-proto'] != 'https')
res.redirect('https://' + req.headers.host + req.url)
else
next() /* Continue to other routes if we're not redirecting */
});
heroku takes care of the rest, setting up an http server which is a mirror of your http server and uses their certs, etc.