http server on top of net server - node.js

I implemented 2 webservers with express. One is the main, one is a microservice.
They are communicating through a HTTP REST API, and we had historically a socket.io server started on the microservice to watch the up/down status from the main server.
----HTTP-----
[main server] [microservice]
--socket.io--
I then realized that socket.io is not the right tool for that. So I decided to trade socket.io for a raw TCP socket.
So the question is : Is that possible to start the http server "ON TOP" of a raw TCP server (on the same port) ? (allowing to connect via TCP client AND to send HTTP requests ?)
I have this so far :
const app = express();
const server = http.createServer(app);
// const io = sio(server);
server.listen(config.port, config.ip, callback);
and I'm trying to integrate with this
What I'm trying to achieve, and achieved successuly with socket.io, is starting a socket server on the microservice, connect to it on the main server, keep it alive, and watch for events to keep a global variable boolean "connected" in sync with it. I'm using this variable to aknowledge the my frontend of microservice state, also to pre-check if I should try to request the microservice when requested, and also for loggin purposes. I'd like to avoid manual polling, firstly for maintenability, and also for realtime purpose.

Is that possible to start the http server "ON TOP" of a raw TCP server (on the same port) ?
Sort of, not really. HTTP runs on top of TCP. So, you could technically open a raw TCP server and then write your own code to parse incoming HTTP requests and send out legal HTTP responses. But, now you've just written your own HTTP server so it's no longer raw TCP.
The challenge with trying to have a single server that accepts both HTTP and some other protocol is that your server has to be able to figure out for any given incoming packets, what it is supposed to do with it. Is it an HTTP request? Or is it your other type of custom request. It would be technically feasible to write such a thing.
Or, you could use the webSocket technique that starts out as an HTTP request, but requests an upgrade to some other protocol using the upgrade header. It is fully defined in the http spec how to do this.
But, unless you have some network restriction that you can only have one server or one open port, I'd ask why? It's a complicated way to do things. It doesn't really cost anything to just use a different port and a different listening server for the different type of communication. And, when each server is listening only for one type of traffic, things are a heck of a lot simpler. You can use a standard HTTP server for your HTTP requests and you can use your own custom TCP server for your custom TCP requests.
I can't really tell from your question what the real problem is here that you're trying to solve. If you just want to test if your HTTP server is up/down, then use some external process that just queries one of your HTTP REST API calls every once in a while and then discerns whether the server is responding as expected. There are many existing bodies of code that can be configured to do this too (it's a common task to check on the well being of a web server).
The code you link to shows a sample server that just sends back any message that it receives (called an echo server). This is just a classic test server for a client to connect to as a test. The second code block is a sample piece of client code to connect to a server, send a short message and then disconnect.
From your comments:
The underlying TCP server wouldn't even be used for messaging, it just would be used to watch connect/disconnect events
The http server already inherits from a TCP server so it has all the same events for the server itself. You can see all those events in the http server doc. I don't know exactly what you want, but there are server lifetime events such as:
listening (server now listening)
close (server now closed)
And, there are server activity events such as:
connect (new client connected)
request (new client issues a request)
And, from the request event, you can get both the httpClientRequest and httpServerResponse objects which allow you to monitor the lifetime of an individual connection, including event get the actual socket object of an incoming connection.
Here's a code example for the connect event right in the http server doc.

Related

How socket and express listen on same port

Hello I have a conceptional dellema.
I wanted to integrated socket.io(real-time communication) after user asks for drive(making an Uber like project).
I got an example here: Medium Article Now as I can see express and socket are listening to the same port. How it can be possible?
Like if I send an http protocol request the app in express picks it up and does the job for me on port 80(say). Now I emit an event. It reaches port 80. How it decides that this goes to socket.io and not to app. On the server there is only 1 port 80. How on the same port, two different protocols are able to understand which request to process.
What my life looks like:
Client opened a random port and send a get request to the server. It is a protocol where data is designed in a particular format. Like header, body etc. Server picks it up and app in express decompiled it for me. Now client wants to open real time communication. He sends a request to open socket. All good. A request is received and socket opened.
Exactly here my life stops. How? How the socket starts to listen on the same port on my server and client? How server processes the request?
I am not able to get the feel of the real time communication with http protocol or any other protocol.
Like if I want to make my socket secure(I mean a particular socket used by particular authenticated user) I do something like:
app.post('/secure', jwt.verify, (req, res) => { });
Now let's say this request is responsible to open a socket connection for sharing of location data like in Uber. Now if I open a socket inside this then it will automatically be secure? Coming from a secure port? What the socket be like?
Please someone get me a feel of what is going on the server side and client side. I just don't understand it even after reading a lot on stack overflow.
There is a server and client may need to open real time communication after some time but how everything fits in?

How to create a nodejs HTTP server with an existing TLS client socket?

I have a nodejs TLS client socket on my laptop, connected to a TLS server socket on a different computer (server). The server cannot connect to my laptop. The laptop needs to initiate the connection.
Now I want the server to make requests to my laptop. The idea is to reuse the HTTP protocol. Is there a way to create a HTTP server using the existing TLS client socket?
This way, the server machine can make a HTTP request, and the client TLS receives it, and the HTTP server would parse it? Or am I missing something?
Once you have a TCP socket open between laptop and server, you can send data either way over that socket. So, if the server wants to send some query to the laptop, it can do so just fine. You will have to invent your own protocol on top of TCP to do that, but it could be as simple as a text/line based protocol if you want.
Or, instead of making a plain TCP connection, you can make a webSocket or socket.io connection from the laptop to the server (instead of the plain TCP connection) and then either side can send messages either way and the protocol part is already taken care of. If you use socket.io, it will automatically reconnect if the connection is interrupted too.
There is no simple way to attach an HTTP server to an existing TCP socket and it would be fraught with difficulties too because an HTTP connection is generally not a continuous connection over which you send many separate requests (advanced versions of http can do that, but I doubt you want to get into implementing all that logic on both ends). You could use the HTTP protocol over your existing TCP socket, but that would probably be substantially more work to implement than just use the webSocket/socket.io idea above.

Is there a way to identify express server-to-server request origin

Is there a way to obtain the origin information of a remote server making requests to my api server? The objective is to prevent possible server-to-server authentication token spoofing.
To test, I basically sent remote requests to the server from a test server listening on port 8000. While the req.connection.remote.address logged by the api server was consistent, the req.connection.remote.port changed with every request.
Is there a way to obtain the address of the test server along with its port 8000 from the request object at the api server? An outside of the box solution would be appreciated as well.
Is there a way to obtain the address of the test server along with its port 8000 from the request object at the api server?
No, there is not unless the requesting server specifically provides that information for you in a non-standard (custom) header. It is not part of TCP/IP or HTTP that you would know anything about what type of http client it is that is making the request or that it's even actually an http server making a request of your http server. From the networking point of view, it's just some http client at some IP address and you don't know anything about what else that http client might be doing (in your case also an http server).
An incoming TCP/IP connection never comes from the public, incoming port of the requesting web server. Instead, it comes from some dynamically assigned outbound port that is likely different for every request. That's how TCP/IP works. Outbound ports are dynamically assigned when the socket is created and they come from a different port range than is typically used for listening for incoming requests.
If the request is originating from a cooperating server, then you can ask it to set a custom header that indicates what port it is running on for incoming requests, but if it's not a cooperating server, there is no way for you to know what port is listens for incoming requests or if even it is a server at all.

What port is used to send request by an Express app?

I have an Express app A, that is configured to listen on 4455 port.
The app also uses axios to send requests to a different server B.
The server B is configured such that it replies to host:port from which it recieved the request.
In this case server A can't recieve response from B, because in the request the, port of A keeps changing.
Does express server send and receive messages from the same port?
The port on which Express listens for incoming connections has nothing to do with the port used for requests that happen to be made from the same application.
Requests are typically made from a random(-ish) port, and it would require some effort if you want that port to be fixed (always the same). In fact, I'm not even sure if you can make axios use a specific local port from which it makes requests.
That leaves the following solution: you make a request using axios, somehow (I'm not sure how) record from which local port that request is being made, and after the request has finished, create a temporary (Express) server that listens for the response on that same local port. When server B has sent its response (or after a specific timeout), that server is stopped.
To be honest, the way that server B sends back its responses is quite uncommon, especially since requests are almost always made from a random port. I also don't understand why server B cannot send back the response over the existing connection.

Expressjs app, using websockets for chat. Use different port for websocket server?

I'm making an app using node.js' express framework which serves both html content over http and uses websockets for a chat feature. I'm wondering how I can accomplish both at the same time. My idea is to use a different port for websocket connections (so http requests would come to port 3000 and websockets would connect on port 3001) but I don't know if that's a good solution. I'm especially worried about deployment to something like heroku and if I can specify different ports for my app.
I'm wondering how I can accomplish both at the same time.
The webSocket protocol is specially designed so it can run on the same port as your regular web server requests. So, you don't need a separate port in order to have both a web server and chat running using webSockets.
This works because a webSocket connection is always initiated with an http request that sets a few special headers. The receiving web server can then detect those special headers and know that this incoming http request is actually a request to initiate a webSocket connection. With a particular response, the client and server then agree to "upgrade" the connection and switch to the webSocket protocol. From that point on, that particular TCP connection uses the webSocket protocol.
Meanwhile any incoming http request that does not have the special webSocket headers on it is treated by your web server as just a regular http request. In this way, the same server and the same port can be used for both webSocket connections and regular http requests. No second port is needed.
Another advantage of this scheme is that the client can avoid the cross-origin issues that it would run into if it was trying to use a different port than the web page it was loaded from.
I'm especially worried about deployment to something like heroku and
if I can specify different ports for my app.
If you were to actually use two ports, then you would need to create two separate servers, one listening on each port since a given server can only listen on one port. In node.js, the two servers could both be in the same node.js app (making it easier to share data between them) or you could put them in completely separate node.js processes (your choice).
And, if you used multiple ports, you'd also have to support CORS so that the browser would be allowed to connect to the separate port (to avoid same-origin restrictions).

Resources