Is http/express required when deploying socket.io web app - node.js

I'm trying to create a real time chat web app using Socket.io.
I used this code for server running on port 3000.
const io = require("socket.io")(3000, {
cors: {
origin: "http://127.0.0.1:5500",
methods: ["GET", "POST"],
},
});
Now I'm thinking of deploying my web app to railway.
I tried deploying the app to railway, it build successfully. Then updated client side with new server link, but it's not working.
I wanted to ask, will I need a web server (http or express) to handle incomming connections.
If yes, then why was it running fine before on my local machine and now it requires a web server.

Related

does socket.io server need to be seperate from backend when deploying?

I am building react app. I have my client folder, and my backend folder that contains all my mongo db models, routes, functions etc...
I know realize that my app needs to use socket.io
My frontend is on localhost:3000 and my backend is on localhost:5000
My understanding is that socket.io needs its own port.
Does this mean when I deploy to heroku I need to deploy a backend server, frontend server, and a socket.io server?
My understanding is that socket.io needs its own port.
This is incorrect. socket.io can use the same port as your backend just fine. Incoming requests to create a socket.io connection can be distinguished from other web requests via a custom header that the underlying webSocket connection protocol uses. This allows socket.io/webSocket and your http server to use the exact same port.
Does this mean when I deploy to heroku I need to deploy a backend server, frontend server, and a socket.io server?
No. You can still just have frontend server and backend server and the backend server can handle both your backend requests and the socket.io connections.

How build to deploy node app to http server

Is there any way to use express or other nodejs librarys to to design an api and deploy it pasting files as a resource path in a web server just like react.
My web server just listen on ports 80 and 443.
I have pages on domain.com/page1 domain.com/page2.
and i want to deploy an api listening on domain.com/page3 but i cant install a nodejs server and proxy requests to page3 to it.
Thanks a lot
There can be only one web server listening on a given port. You can directly "listen to a path", only a port.
So, if you already have an existing web server running on ports 80 and 443, then these are your options.
Modify your existing web server to add your API server code to it so it can handle requests for http://yourdomain.com/page3 and https://yourdomain.com/page3 directly with your API.
You can add some middleware to your existing web server to make it a proxy for http://yourdomain.com/page3 that will redirect requests to your http://yourdomain.com:3000/page3 Express-based API server.
Run your own Express-based API server on your own separate port and access the API server directly via the separate port such as http://yourdomain.com:3000/page3.
You can install a proxy such as nginx in front of your existing web server and have it redirect incoming requests to http://yourdomain.com/page3 and https://yourdomain.com/page3 to the separate port that your Express-based API server is running on.

Socket.io/Hapi Not Working Azure App Service (Linux)

I recently made a switch in our test environment from an Azure App Services Windows to Linux. Everything is working as it was previously except our socket connections. There seems to be a lot of outdated information regarding the Linux App Service, and the documentation is lackluster. However, according to these release notes, support is available for web sockets on Azure App Service Linux.
In some of Azure App Service for Linux documentation, it states that you must disable perMessageDeflate in order to get Web Sockets to work with Linux App Service and NodeJS. I believe I have done that in my HapiJS server code below. I have verified with a console.log(io) that the setting perMessageDeflate seems to be set to false correctly.
import Server from 'socket.io';
import socketioJwt from 'socketio-jwt';
const myHapiJSPlugin = {
name: 'myPluginName',
version: '2.0.0',
register: function (server, options) {
const io = new Server(server.listener, {
perMessageDeflate: false,
transports: ['websocket'],
origins: '*:*'
});
io.use(socketioJwt.authorize({
secret: JWT_SECRET_KEY,
handshake: true
}));
io.on('connection', socket => {
console.log(io);
// more code here
};
};
};
When I open the network page of Chrome's console while using my web client, I get a 101 response code from the server. I console.log connects/disconnects from the socket.io's client's callbacks. I can see it continually connects/disconnects despite getting an acknowledgement from the server (101 response). The state of the connections says 'stalled' in the console. I seem to be subscribing to a particular route okay as the callback fires.
I have made no other code changes since switching from Azure App Services Windows despite the configuration below to add perMessageDeflate and origins for testing socket.io docs. I'm thinking something is going wrong during the handshake or authentication.
Status Code: 101 Switching Protocols
Access-Control-Allow-Origin: *
Connection: Upgrade
Date: Tue, 01 Oct 2019 18:04:57 GMT
Sec-WebSocket-Accept: <HASH>
Server: Kestrel
Upgrade: websocket
I also added perMessageDeflate to my client side code. It didn't make a difference.
const client = new io(URL, {
query: 'token=' + jwt,
perMessageDeflate: false,
transports: ['websocket'],
upgrade: false
});
What else am I missing? How do I enable web sockets on Azure App Service Linux? I checked for a configuration setting like with Windows. There does not appear to be a setting for that - as it seems web sockets are enabled by default. I have verified in the logs that the web server is not continually restarting causing the connect/disconnects.
Do your WebSockets work if the Authentication is turned off?
I only experience problems with WebSockets using Linux Apps when I enable the Authentication features.
I believe this is due to a poor implementation of the EasyAuth proxy, and that it is considered a difficult problem for MS to fix.
tl;dr
Disable CORS and AUTH through the portal on Linux App Service.
Disable CORS by going to your App Service, select CORS on the left side menu bar under API, remove any entries in there. By removing all entries, you are disabling Azure's CORS implementation for App Service.
Disable AUTH by going to Authentication/Authorization under the Settings heading on the left side menu bar. Click the switch to 'off'.
This will allow Web Sockets to work as expected with Linux App Service. However, you need to configure CORS and AUTH with your web server framework now.
Long Form
After hearing back from my MS support rep, she confirmed that when CORS or AUTH is enabled it breaks Linux App Service's sockets implementations. The Linux App Service CORS and AUTH features are not implemented yet by Microsoft.
In order to use Linux App Service and utilize the CORS or AUTH features, you simply can't because it's not implemented. The official recommended solution is to switch to Windows App Service.
Despite what the Azure documentation states, perMessageDeflate is not required for WebSockets to work with socket.io. I have it working without it correctly. To configure CORS for the App Service from the portal, it's the same as you would for Windows. You can go to your App Service in the portal, select CORS on the left side menu under API. Delete any entries in there to disable App Service's CORS feature. I had only one entry (*) that I was using during testing since I had CORS configured correctly with my Windows App Service before switching to Linux.
If you remove all entries, you should have functioning Web Sockets without CORS. However, keep in mind, you should configure CORS with your web server framework for security reasons. If it's express with socket.io, you'll have to do something like this. Most web frameworks follow a similar paradigm by specifying it on your server object as an option.
There some more information regarding this in this thread on GitHub.
I had similar issues on Node. socket.io was failing on App services run on Linux on an azure cdn hosted domain.
Was able to mitigate this by using the Custom Domain and TLS/SSL settings to link my domain to the app service url instead of setting up an azure cdn on the app service.

Connection between frontend server (Node JS and Angular JS) with backend server (.NET API)

I am having an issue with the connection between my frontend server and the backend server. Both solutions are hosted as Web Apps in Azure. The frontend solution is an Angular solution with a Node server, and the backend solution is an API in .NET.
Both solutions are working good without problems, but I want to filter the connections with the API. I mean, I want to set that the IP from the web app in where I hosted the frontend solution is the only IP which is able to connect to the API. But the IP that the API receives is the IP from the client, not from the server in where the web app is hosted, so I need to know what is happening there. I thought that if an user connects to the frontend solution, and the frontend solution calls to an API, the API should receive the IP from the server in where is hosted the frontend solution, not the IP from the client.
I am using Express and this would be the server.js file in Node:
const express = require('express');
const app = express();
app.use(express.static(__dirname + '/public'));
app.listen(8080);
Something like:
User (IP: X) -----> Frontend Solution (IP: Y) -----> Backend Solution (IP: Z)
Backend Solution should allow the IP Y and deny the IP X.

Running GraphQL server on Google Cloud App Engine

In node.js to run the endpoint locally, I use the following snippet in my app.js
app.use('/graphql', (0, _expressGraphql2.default)(function (req) {
return {
schema: _schema2.default,
pretty: true,
context: _extends({ db: _models2.default }, (0, _isUser2.default)(req.headers['authorization'].split(' ')[1]))
};
}));
app.listen(8080, function () {
However, my app isn't receiving any response from the endpoint on trying to reach hostname:8080/graphql. This works on my local machine.
The title of your post indicates that your node.js app is deployed in Google App Engine. There is no need to worry about assigning an IP address to your instance in that environment. Instances are managed by the App Engine, and so is the routing of requests to your application.
To access the app, once deployed to the App Engine, one only needs to address it following the pattern: app_name.appspot.com. Alternatively, for a custom domain, you can follow the “Using Custom Domains and SSL” guide [1]. Sub-chapter “Adding SSL to your custom domain” of this document may help you with the setting up of SSL, if needed.
The app listens on port 8080 by default in the app engine. This is of no concern to an outside caller, who can only use the following the pattern: app_name.appspot.com to call the app. This situation is valid for the app engine environment.
[1] https://cloud.google.com/appengine/docs/flexible/nodejs/using-custom-domains-and-ssl

Resources