socket.io connection fails when node.js deployed to Google App Engine - javascript

Here's a slice of the code I can run locally just fine:
Server:
var app = require('express')();
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
res.setHeader('Access-Control-Allow-Credentials', true);
next();
});
app.get('/', function (req, res) {
console.log("Got '/'");
res.status(200).send('Hello, world!');
});
var server = app.listen(process.env.PORT || '80', function () {
console.log('App listening on port %s', server.address().port);
});
var io = require('socket.io')(server);
io.on('connection', function (socket) {
console.log("connection");
});
Client: (TypeScript, run from a separate app on a different port, http://localhost:8080)
this.socket = io("http://localhost");
this.socket.on("connect", () => this.onSocketConnect());
When the server si deployed on Google App Engine, and the client is run locally with the address changed to http://my-app-id.appspot.com I get the following error:
WebSocket connection to 'ws://my-app-id.appspot.com/socket.io/?EIO=3&transport=websocket&sid=-Qr3YEeyZLk9K3zmAAAC' failed: Error during WebSocket handshake: Unexpected response code: 400
What's causing this and how can I fix it? Also, once I get this running, I plan to change to https, anything I need to be careful of there?

At this time, connections to App Engine applications over the ws or wss protocols is not supported. It is possible to get the IP of instance serving the initial requests and then connect to that instance directly but this circumvents App Engine's load balancer which sort of defeats the purpose of deploying your application to App Engine in the first place.
There is currently an open issue (Issue 2535: Web Sockets API) on the App Engine public issue tracker. Feel free to star this issue to support it and receive updates.

Related

serving client + socket io from backend

Serving a vue js + socket io client from a node js server (with socket io obviously)
while developing i was connecting and awaiting calls from localhost:8000
new Websocket(
new Server(server, {
cors: {
origin: "http://localhost:8000",
methods: ["GET", "POST"],
},
}),
);
but now, obviously, there is no longer localhost:8000 and I am serving my client's dist/index.html through my webserver as a static file
app.use(express.static(path.join(__dirname, "../../client/dist")));
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname, "../../client/dist/index.html"));
});
I feel like I am missing something really really simple? am I supposed to host my client on a different "web server" if i want to use the socket.io functionality?
as in create a simple web server for the client - and serve it from there on port 8000? and run my own server seperatly ? on port 3000?
I'm hosting this on an EC2 container on aws
I've figured it out - I need to connect to the machine's ip instead of localhost through the client's app - cause localhost:3000 doesn't actually exist...otherwise everything else is ok

How to convert local server to online server Node.js

I've been developing this game for a school project. It is supposed to be online multiplayer, but this far i have online used it locally. I can figure out how to change my server code for it to be able to act as a "real" online server.
The server code:
// Dependencies
var express = require('express');
var http = require('http');
var path = require('path');
var socketIO = require('socket.io');
var app = express();
var server = http.Server(app);
app.set('port', 5000);
app.use('/static', express.static(__dirname + '/static'));
// Routing
app.get('/', function(request, response)
{
response.sendFile(path.join(__dirname, 'index.html'));
});
// Starts the server.
server.listen(5000, function()
{
console.log('Starting server on port 5000');
});
// Add the WebSocket handlers
io.on('connection', function(socket)
{
console.log('New player arrived');
});
Would appreciate any help greatly.
Most of the shared servers run at port 8080
so you may change the port then upload it into the hosting, If you just need it to be live u can use https://heroku.com/ so u can deploy it there
also here's quick option
npm install -g localtunnel
lt --port 8000
You will receive a URL, for example, https://school.localtunnel.me, that you can share with anyone for as long as your local instance of lt remains active. Any requests will be routed to your local service at the specified port
For more info: https://localtunnel.github.io/www/

Express server routes not being hit. Browser Error 'No Data Received ERR_EMPTY_RESPONSE'

I'm having an issue with my express server with an email service I was attempting to set up. After troubleshooting I decided to boil it down and attempt see if the issue would replicate with a simple 'hello world' example, which it did. No routes will be work correctly each request, whether done by a js frontend, postman, or just in a chrome browser will work. Each request will just 'spin' until it returns a 'No Data Received ERR_EMPTY_RESPONSE' error.
I've tried reinstalling the express dependency, reinstalling node itself, different browsers. The code is attached, any help would be appreciated.
const express = require('express');
const cors = require('cors');
const app = express();
let port = 3000;
app.use(cors);
app.get('/testroute', (req, res) => {
console.log('route hit');
res.send('test success');
});
app.listen(port, () => {
console.log('server started on port: ' + port);
});
Change this:
app.use(cors);
to this:
app.use(cors());
Your server was hanging because you were passing cors as middleware. But, cors by itself is not middleware. When Express called it, it never sent a response or called next() to continue routing, so therefore the client was just left hanging forever waiting for a response. Instead, the cors library is designed to that you call it as in cors() to get back a middleware function that you then pass to Express.
This is fully documented in the cors library documentation.

Node.js with express and websocket giving error during WebSocket handshake: Unexpected response code: 200

So I am trying to set up a website that also has websockets where both the http-server and the websocket listens on the same port:
const WebSocket = require('ws');
var express = require('express');
var app = express();
wss = new WebSocket.Server({server : app});
app.get('/', function(req, res){
res.send('hello world!');
});
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});
ws.send('some text');
});
app.listen(8080, function(){
console.log('app started');
});
If I then load the servers website in chrome-browser I am greeted with "hello world!". So far so good. But if I open up the webconsole and try to connect with
var exampleSocket = new WebSocket("ws://192.10.10.30:8080");
I get the following errormessage:
WebSocket connection to 'ws://192.10.10.30:8080/' failed: Error
during WebSocket handshake: Unexpected response code: 200
My first thought was, do I have to explicitly declare an http-server ?
But I read this post
Serve WebSocket and HTTP server at same address on Node.js and there was no http-server explicitly declared. Please help me on this.
You're passing an Express app instance as server, which should be an HTTP/HTTPS server instance. Such an instance is returned by app.listen:
var app = express();
var server = app.listen(8080, function(){
console.log('app started');
});
wss = new WebSocket.Server({server : server});
I was having this issue on a Windows machine and discovered the reason was IIS did not have the WebSocket Protocol turned on. Ensure IIS on the machine supports WebSocket:
Control Panel -> Programs and Features -> Turn Windows features on or off.
Expand Internet Information Services, expand World Wide Web Services, expand Application Development Features, and then ensure WebSocket Protocol is checked.

Running deployd and angular.js app on the same server

I'm trying to run a deployd API on the same server as my AngularJS app, but deployd seems to be conflicting with the app routing.
My deployd server is listening on port 5000 and looks like this:
var deployd = require('deployd');
var server = deployd({
port: process.env.PORT || 5000,
env: 'production',
db: {
host: 'localhost',
port: 27017,
name: 'deployd',
credentials: {
username: 'myUsername',
password: 'myPassword'
}
}
});
server.listen();
server.on('listening', function() {
console.log("Server is listening");
});
server.on('error', function(err) {
console.error(err);
process.nextTick(function() { // Give the server a chance to return an error
process.exit();
});
});
My node server for the AngularJS app is listening on port 3000 and looks like this:
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
app.listen(process.env.PORT || 3000);
The app loads fine, although it is not hitting the API as expected when making a call like this:
$http.get('localhost:5000/foo')
or this:
$http.get('http://my.public.ip.address:5000/foo')
And my page routing (in HTML5 mode, with no # in the URL) is getting hijacked by deployd -- so a URL routed by AngularJS for '/foo' is hitting the API and returning "Cannot GET /foo".
This is all happening on a server that is also running Apache, but that is configured to forward requests for my domain to port 3000 using something like this:
NameVirtualHost *:80
<VirtualHost *:80>
ServerAdmin webmaster#localhost
ServerName my.domain.com
ProxyPreserveHost on
ProxyPass / http://localhost:3000/
<Location />
Order allow,deny
Allow from all
</Location>
</VirtualHost>
If I use the # in the URL, like http://my.domain.com/#/foo that will return the page template dictated by the AngularJS router, but it is missing data because the API is not being hit on port 5000.
Any help would be greatly appreciated.
Turns out this was a problem with my Express server.js code and had nothing to do with Deployd. I kept seeing the Cannot GET /foo message and just assuming Deployd was trying to fetch a resource, but in fact Express was not loading index.html (which loads AngularJS and my routing code), because it was just trying to load a static file called foo instead.
Here is my fixed server.js:
var express = require('express');
var app = express();
app.use(express.static(__dirname + '/public'));
app.use(function(req, res) {
res.sendfile(__dirname + '/public/index.html');
});
app.listen(process.env.PORT || 3000);
Now, if the static file foo does not exist, it loads index.html and allows my AngularJS router to take the wheel.
have you checked that from a browser that port 3000 as well as 5000 is reachable?
Because you are using proxy pass it makes me think that those ports aren't open. And because angular is run client side, it will never be able to connect to the api if the 5000 port is closed.

Categories

Resources