Node.JS HTTP/HTTPS/etc requests through proxy tunnel - node.js

I have a proxy "net" connection and I need to send request to some different domains and protocols (http, https, ftp, etc.) with one stable connection to proxy server.
var socket = net.connect(
1111, // proxy port
'xx.xx.xxx.xx' // proxy host
);
socket.on('connect', function(a) {
console.log('--- connect', socket.remoteAddress);
// connecting to https host
socket.write(
'CONNECT www.google.com:443 HTTP/1.1\r\n' +
'Proxy-Connections: keep-alive\r\n' +
'Host: www.google.com\r\n\r\n',
function() {
// send GET request and wait for response
socket.write(
'GET / HTTP/1.0\r\n' +
'User-Agent: Node.js/0.6.6\r\n' +
'Connection: keep-alive\r\n' +
'Host: www.google.com\r\n\r\n',
function(a) {
return socket;
}
);
/*
another requests to different protocols/ports...
socket.write(...)
*/
return socket;
});
});
socket.on('data', function(a) {
console.log('--- data', a.toString());
});
socket.on('drain', function() {
console.log('drain!');
});
socket.on('timeout', function() {
console.log('timeout!');
});
socket.on('close', function() {
console.log('Connection closed');
});
socket.on('end', function() {
console.log('Connection end');
});
After execution I have next result:
--- connect xx.xx.xxx.xx
--- data HTTP/1.0 200 Connection established
Connection end
Connection closed
There is only one response as "Connection established" but I cant reach response from "GET" request. Connection is closed after receiving response.
Where I'm wrong? Googled it but found only one solution - create different connections for http or another protocols and for https, but I need to send requests from only one stable connection.

Related

how to keep alive the TCP client connection after end in node js

i need your help... i am new to TCP..
I had implemented TCP server and client... tcp server write data when connection is established and wait for kernal buffer getting empty then i emit end event from TCPserver and same as client received data from server in end event...
TCP server.js
const TCPserver = net.createServer().listen(4040);
var recvData='';
TCPserver.on('connection',(TCPclient)=>{
TCPclient.setKeepAlive(true);
console.log(`TCP Client Connected ${TCPclient.localAddress}:${TCPclient.localPort}`);
var strData=JSON.stringify({"msg":"testRequest from Cortana"})
var is_buffer_null=TCPclient.write(strData);
if(is_buffer_null){
TCPclient.end();
}
TCPclient.on('data',(data)=>{
recvData+=data;
})
TCPclient.on('end',()=>{
console.log("Packet is received : "+recvData);
recvData='';
})
TCPclient.on('drain',()=>{
TCPclient.end();
})
TCPclient.on('error',(err)=>{
console.log(err);
})
TCPclient.on('close',(hardError)=>{
console.log("Client disconnected");
if(hardError){ console.log("TCP error"); }
})
})
TCPclient.js
var TCPcortana = net.connect({ port: 4040, host:'127.0.0.1',allowHalfOpen:true},()=>{
console.log(`server connected to ${TCPcortana.localAddress}:${TCPcortana.localPort} `);
});
TCPcortana.setKeepAlive(true);
TCPcortana.on('data',(data)=>{
recvData+=data;
})
TCPcortana.on('end',()=>{
console.log("Packet is received : "+recvData);
processReq(recvData);
recvData='';
})
TCPcortana.on('drain',()=>{
TCPcortana.end();
})
TCPcortana.on('error',(err)=>{
console.log(err);
setTimeout(()=>{
TCPcortana.connect({ port: 4040, host:'127.0.0.1',allowHalfOpen:true});
},10000)
})
TCPcortana.on('close',(hardError)=>{
console.log("connection disconnected");
if(hardError){ console.log("TCP error"); }
})
function processReq(data) {
console.log("Packet being processed");
var stringData=JSON.stringify(data);
var is_buffer_empty=TCPcortana.write(stringData);
if(is_buffer_empty){
TCPcortana.end();
}
}
the Tcp client send responses then the client connection close, i am expecting the client was not closed and keep alive the connection between and server and client... please help me...
If you are trying to frequently send messages to the client without closing the connection, you need to use server send events.
Server Sent Events continue to keep the connection alive and the server can send "events" containing some data.
See this answer for more details.

Angular 6 authentificate client after server restart socket.io socketio-jwt

Id like to auth eacht socket.io event on server side.
When i open angular page first, call method initSocket(login: Login), its ok.
Authentification successfull and i can send a message to server.
But if i restart server, angular reconnect to server by Htttp, but cant send a message by socketio.
In my server no messages in logs.
It seems that socketio-jwt block an clients message.
If i press F5 on client side its still ok again.
How to solve it without refreshing a page?
It seems taht i have to pass a token to each event on client side, after connection established to, but i dont know how to do it.
Angular 6:
public initSocket(login: Login): void {
this.socket = socketIo(SERVER_URL);
console.log('Socket init at' + SERVER_URL);
this.socket.emit('authenticate', { token: this.login.token });
this.socket.on('authenticated', function () {
console.log('socket is jwt authenticated');
});
this.socket.on('unauthorized', function (error, callback) {
if (error.data.type === 'UnauthorizedError' || error.data.code === 'invalid_token') {
// redirect user to login page perhaps or execute callback:
callback();
console.error('Users token has expired');
}
});
this.socket.on('disconnect', function (error) {
console.error('socket disconnect', error);
});
this.socket.on('connect_failed', function (error) {
console.error('socket connect_failed');
});
}
Server side:
io.sockets
.on('connection', socketioJwt.authorize({
secret: environment.secret,
timeout: 15000,
callback: false
})).on('authenticated', function (socket) {
clients[socket.decoded_token.id] = socket.decoded_token.login;
console.error('Connected: ', socket.decoded_token.login);
socket.on('message', async function (data) {
try {
// Проверка что пользователь пишите от себя
if (data.from === socket.decoded_token.id) {
data.totalCount = await db_helper.saveMessage(data);
if (clients[data.from] && clients[data.to]) {
io.sockets.connected[clients[data.to].socket].emit("message", data);
console.log("Sending from: " + clients[data.from].name + " to: " + clients[data.from].name + " '" + data.text + "'");
} else {
console.log('User does not exist: from=>', data.from, ':', clients[data.from], 'to=>', data.to, ':', clients[data.to]);
}
}
}
catch (error) {
console.error(error.message);
}
});
//Removing the socket on disconnect
socket.on('disconnect', function () {
});
});
This is because whenever your server/client goes offline, a new socket is created for re connection purpose and to establish a new connection i.e re connection, Server disconnects all it's previous connection from the same client, this process is asynchronous and thus is not visible to developers easily.
I would have also checked if my socket reconnection which is done is reconnected to the , by default socket reconnects to the port your client is connected to.
if that's the case then you need to reconnect with the help of io (socket manager)
There is also a possibility that your client re connection is set to false, you can check your socket properties by consoling it as follows:
this.socket.on('disconnect', function (error) {
console.log('disconnected', this)
//this sets whether the re connection is allowed or not
this.io._reconnection = true;
});
this.socket.on('reconnect', (error, callback) => {
console.log('reconnect succesfully', this);
//connect to the previously connected socket.
this.io.socket.reconnect()
});

can't get response from websocket rxjs node Angular

Trying to get a WebSocket working using rxjs webSocket
I set up a node server, that throws no errors at the moment, but it doesn't send messages to the server or connected users
It seems to work better when I use 'ws://echo.websocket.org/', I see messages echoed back to me, however, I don't see messages sent, in other open browsers, basically no communication between users, that are supposed to be subscribed to the websocket
All I want is a simple way of carrying simple info between users
index.js
var express = require('express');
var WebSocketServer = require('websocket').server;
var app2 = express()//There is already another app var for main app server
var server2 = http.createServer(app2);
var server2 = app2.listen(8081, function () {
console.log((new Date()) + ' Server is listening on port 8081');
})
wsServer = new WebSocketServer({
httpServer: server2,
autoAcceptConnections: false
});
function originIsAllowed(origin) {
if (origin === 'http://localhost:1234'){
return true;
}
// put logic here to detect whether the specified origin is allowed.
}
wsServer.on('request', function(request) {
if (!originIsAllowed(request.origin)) {
// Make sure we only accept requests from an allowed origin
request.reject();
console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
return;
}
var connection = request.accept(null, request.origin);
console.log((new Date()) + ' Connection accepted.');
connection.on('message', function(message) {
// console.log(message)
if (message.type === 'utf8') {
console.log('Received Message from: ' + connection.remoteAddress);
connection.sendUTF(message.utf8Data);
}
else if (message.type === 'binary') {
console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
connection.sendBytes(message.binaryData);
}
});
connection.on('close', function(reasonCode, description) {
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
});
});
in my clientside socket service:
import { Injectable } from '#angular/core';
import { Observable } from '../../../node_modules/rxjs';
#Injectable()
export class SocketService {
socket$ = Observable.webSocket( 'ws://localhost:8081');
// 'ws://echo.websocket.org/'
constructor() {
this.connectToSocket()
}
connectToSocket(){
this.socket$.subscribe(
(message) => console.log('message received: ' + message),
(err) => console.log(err),
() => console.log('complete')
);
}
}
And to send message, from another component, I use:
this.socketService.socket$.next(JSON.stringify('test'))
According to the documentation of WebSocket-Node (https://github.com/theturtle32/WebSocket-Node/blob/master/docs/WebSocketServer.md), you have to programatically accept each connection before continuing the handshake.
You can instead set the autoAcceptConnections option of your server config to true, like this:
const wss = new WebSocketServer({ httpServer: server2, autoAcceptConnections: true });
If you do indeed have custom request checking requirements, you can use either accept or reject inside your request handler, like this:
request.accept('chosen-protocol', 'accepted-origin')
or
request.reject()

Primus websocket server failed to read message from client

I use Primus to create a websocket server. And I use wscat command to test that server. It is able to connect to the websocket server. But the server can't receive any messages from the client. Below is the Primus code:
http = require('http');
server = http.createServer();
Primus = require('primus');
primus = new Primus(server, {
transformer: 'websockets',
pathname: 'ws'
});
primus.on('connection', function connection(spark) {
console.log("client has connected");
spark.write("Herro Client, I am Server");
spark.on('data', function(data) {
console.log('PRINTED FROM SERVER:', data);
spark.write('receive '+data)
});
});
server.listen(5431);
console.log("Server has started listening");
And below is the way I tested it:
$ wscat -c http://localhost:5431/ws
connected (press CTRL+C to quit)
< "Herro Client, I am Server"
> hello
>
from the above commands you can see that the client can receive message when request the connection. But then I send a 'hello' to the server and the client doesn't receive the feedback message from server. And the server doesn't print the 'hello' message either. Is there anything wrong with my code? It seems that spark.on('data', function(data) method has no effect.
You were throwing a spark error by not sending valid JSON data to the server.
message: 'Failed to decode incoming data: Unexpected token a in JSON
at position 0'
Try this:
http = require('http');
server = http.createServer();
Primus = require('primus');
primus = new Primus(server, {
transformer: 'websockets',
pathname: 'ws'
});
primus.on('initialised', function() {
console.log('Primus Initialized.');
});
primus.on('connection', function connection(spark) {
console.log("client has connected");
spark.write("Herro Client, I am Server");
spark.on('data', function(data) {
console.log('PRINTED FROM SERVER:', data);
spark.write('received');
});
spark.on('heartbeat', function() {
console.log('hearbeat...');
});
//happens after primus.disconnection
spark.on('end', function() {
console.log('spark end');
});
spark.on('error', function (v) {
console.log('spark error', v);
});
});
//happens before spark.end
primus.on('disconnection', function (spark) {
console.log('primus disconnection');
});
primus.on('error', function error(err) {
console.log('primus error', err.stack);
});
server.listen(5431);
It worked for me as shown below:
$ wscat -c 127.0.0.1:5431/ws/websocket
connected (press CTRL+C to quit)
< "Herro Client, I am Server"
> {"a":"b"}
< "received"
> {"valid":"json"}
< "received"

Allow websocket connection only from one URL

My websocket application accepting connections like this:
wsServer.on('request', function(request) {
console.log(request);
if(request.origin == "https://www.my-domain.com"){
var connection = request.accept(null, request.origin);
/* some lines of code
...
*/
} else {
//here I want block request
}
Is here some function like .decline()? or .notAccept() or...?
When I trying connect to my websocket from different URL, my status is "pending" for a long time.
It's shown here:
wsServer.on('request', function(request) {
if (! originIsAllowed(request.origin)) {
// Make sure we only accept requests from an allowed origin
request.reject();
console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
return;
}
...
});
You'd have to replace originIsAllowed(request.origin) with your own check.

Resources