node.js websocket data transfer calculation - node.js

i proxy websocket with following code, and i want know how i can calculate how much data transferred(upload/download), i used data event but received number is inconsequent
var http = require('http'),
httpProxy = require('http-proxy');
console.log('connected')
var proxy = new httpProxy.createProxyServer({
target: {
host: 'someIP',
port: 30534,
}
});
var proxyServer = http.createServer(function (req, res) {
proxy.web(req, res);
});
let byte= 0
proxyServer.on('upgrade', function (req, socket, head) {
proxy.ws(req, socket, head);
//here not working as well, the number is not real
req.socket.on('data', (message) => {
byte+= Buffer.byteLength(message)
console.log('megaByte ', megaByte / 1000 / 1000)
})
proxy.on('error', (err) => {
})
proxy.on('proxyRes', function (proxyRes, req, res) {
console.log('RAW Response from the target', JSON.stringify(proxyRes.headers, true, 2));
});
});
proxyServer.listen(8015);

Related

Node.js: Is there a way to mock the prometheus pushgateway server?

I am using node.js package prom-client to try to push different custom metrics to the Prometheus Pushgateway server.
The code is working and now I am writing the test code for the functionality. I wonder whether there is a way to mock the Prometheus Pushgateway server?
I had tried to use a normal express API server (like the following)
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
let data = null;
// ROUTES FOR OUR API
// =============================================================================
const router = express.Router();
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
router.get('/', (req, res) => {
console.log("pushgateway server: get to '/' received");
res.json(data);
});
router.post('/', (req, res) => {
console.log("pushgateway server: post to '/' received");
console.log(req.body);
data = req.body;
res.send('POST request to the homepage');
})
app.use(router);
// API JSON BASED ERRORS
// =============================================================================
app.use((err, req, res, next) => {
if (req.xhr) {
console.error(err);
res.status(500).send({ err: 'Something failed!' });
} else {
next(err);
}
});
app.use((err, req, res, next) => { // eslint-disable-line
console.error(err);
res.status(500).send({ err: err.message });
});
// START THE SERVER
// =============================================================================
const port = 9876;
const server = app.listen(port, '0.0.0.0');
console.log(`Prometheus Pushgateway Mock Server is listening on port ${port}`);
// SHUTDOWN HANDLING
// =============================================================================
// Nodemon Signal Handling
process.once('SIGUSR2', () => {
console.log('Received kill signal, attempting gracefully close');
server.close(() => {
console.log('Closed out remaining connections');
process.kill(process.pid, 'SIGUSR2');
});
setTimeout(() => {
console.error('Timeout, forcefully shutting down');
process.kill(process.pid, 'SIGUSR2');
}, 3000);
});
module.exports = server;
but it did not work -- when I call gateway.pushAdd() on my test code, the server did not receive any post message.
Can anyone give me some hints on how to do this (mock the prometheus pushgateway server)?
There are different options out there to mock a third party http server. Here are 3:
Nock
Dyson
Stubborn
Disclaimer: I am the maintainer behind stubborn.
Nock and Dyson are the most popular ones, they have pro and cons. Stubborn is more recent and tries to cover some limitations of Nock and Dyson.
You can checkout this reddit post first comment I wrote for a comparison between the 3 solutions.
So I have solved the problem by creating a simple http server.
The following is the code of the server:
const http = require('http');
const body = [];
let text = null;
let path = null;
function createServer(port) {
return http.createServer()
.on('request', (req, res) => {
if (req.method === 'POST' || req.method === 'PUT') {
path = req.url;
req.on('data', (chunk) => {
body.push(chunk);
}).on('end', () => {
text = Buffer.concat(body).toString();
res.end(`${req.method} success`);
}).on('error', (err) => {
console.error(err);
});
} else if (req.method === 'GET') {
res.end(JSON.stringify({ path, text }));
} else if (req.method === 'DELETE') {
path = null;
text = null;
res.end('DELETE success');
}
}).on('error', (err) => {
console.log(`Server error: ${err}`);
})
.listen(port, '0.0.0.0');
}
module.exports = (createServer);
The server accepts POST/PUT/DELETE/GET requests, to handle the pushAdd()/push()/delete() functions of the gateway to handle the metric data, as well as checking the push data on the mocked pushgateway.
Also, the request.url and the text data pushed to the server are saved and passed to the test program for verification.
The following is one of the test cases (using Mocha+Chai):
describe('Check adding custom push count metric', () => {
it('Check connection: should return - network status: 200, result contains custom count metric string', async () => {
metricInstance = promMetric.createCustomPushMetric({
name: 'test_counter',
help: 'Used to test the pushgateway for custom counter metrics',
type: 'counter',
jobName: 'custom-metric-pushgateway-counter',
groupings: { key: 'test', type: 'customMetric' },
});
await promMetric.addPushMetric(metricInstance, 0.879);
await sleep(500);
const result = await chai.request(mockPgwServer).get('/');
expect(result).to.have.status(200);
const json = JSON.parse(result.text);
expect(json.path).to.equal('/metrics/job/custom-metric-pushgateway-counter/key/test/type/customMetric');
expect(json.text).to.match(/# HELP Push_gateway_test_test_counter Used to test the pushgateway for custom counter metrics/);
expect(json.text).to.match(/# TYPE Push_gateway_test_test_counter counter/);
expect(json.text).to.match(/Push_gateway_test_test_counter 0.879/);
});
});
The "path" and "text" stored in the server when the metric is posted from the client are sent back to the client when queried and verified.

ERR_HTTP_HEADERS_SENT node js socket connection

I am building an API that uses socket connection to interact with a server backend built in C#. This is what I have so far
const request = require('request');
const express = require('express');
const app = express();
var server = require('http').createServer(app);
var cors = require("cors");
app.use(cors());
const net = require('net');
const client = new net.Socket();
const stringToJson=require('./stringToJson')
const port = process.env.PORT;
const host = process.env.HOST;
client.keepAlive=true
client.on('close', function() {
console.log('Connection closed');
});
app.get('/getScores',function (req,res) {
let dataSend=''
client.on('data', function (data) {
console.log('Server Says : ' + data);
if(data!='ANALYSIS-ERROR'){
dataSend=stringToJson.stringToJson(data)
}
else{
dataSend=stringToJson.stringToJson('0:0.0:0.0:0.0:0:0:0.0:0.0:0.0:0.0:0.0:0:0.0:0.0:0.0:0.0:0.0:0:0.0:0.0:0.0:0.0:0.0:0:0.0:0.0:0.0:0.0:0.0')
}
client.destroy()
return res.send(dataSend)
});
client.connect(port, host, function () {
client.write(`GENERAL-ANALYSIS|${req.query.id}|${req.query.website}|`)
return
});
return
})
app.get('/getPlace',function (req,res) {
console.log(req.query)
request(
{ url: `https://maps.googleapis.com/maps/api/place/textsearch/json?query=${req.query.name}+in+${req.query.city}&key=${process.env.API_KEY}` },
(error, response, body) => {
if (error || response.statusCode !== 200) {
return res.status(500).json({ type: 'error', message: error.message });
}
return res.json(JSON.parse(body));
}
)
})
//TODO ADD 404 500 PAGES
app.use((req, res, next) => {
res.status(404).send("Sorry can't find that!");
});
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('Something broke!');
});
server.listen(9000, () => {
console.log(`App running at http://localhost:9000`);
});
Basically it creates a connection with the server and listens for some data to be sent back. Then processes the string and sends it to the React frontend. The api calls are made by the frontend using axios
It works but if you refresh the page it throws this error Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
How do I fix this?
Try setting the headers as found in the documentation request.setHeader(name, value)
request.setHeader('Content-Type', 'application/json');

How to subscribe a HTTP endpoint to SNS in node js?

I am trying to subscribe my endpoint to a topic (I am using an EC2 instance), I have tried visiting my endpoint in a browser (GET request) to call sns.subscribe but I am not receiving a POST request afterwards.
The response I get from calling sns.subscribe is this.
{ ResponseMetadata: { RequestId: 'xxxx-xxxx-xxxx-xxx-xxxx' },
SubscriptionArn: 'arn:aws:sns:topic_location:xxxx:topic_name:xxxx-xxxx-xxxx-xxx-xxxx' }
This is my code.
const express = require("express");
const AWS = require('aws-sdk');
const request = require('request')
const bodyParser = require('body-parser')
const app = express();
var SNS_TOPIC_ARN = "arn:aws:sns:topic_location:xxxx:topic_name";
// configure AWS
AWS.config.update({
'accessKeyId': 'mykey',
'secretAccessKey': 'mysecretkey',
"region":"myregion"
});
const sns = new AWS.SNS();
app.get('/', (req, res) => {
var params = {
Protocol: 'http', /* required */ //http , https ,application
TopicArn: SNS_TOPIC_ARN, /* required */ // topic you want to subscribe
Endpoint: 'http://ec2-xx-xx-xx-xxx.myregion.compute.amazonaws.com/:80', // the endpoint that you want to receive notifications.
ReturnSubscriptionArn: true //|| false
};
sns.subscribe(params, function (err, data) {
if (err) {
console.log(err);
} else {
console.log(data);
}
});
res.end();
});
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.post('/', (req, res) => {
let body = ''
req.on('data', (chunk) => {
body += chunk.toString()
})
req.on('end', () => {
let payload = JSON.parse(body)
if (payload.Type === 'SubscriptionConfirmation') {
const promise = new Promise((resolve, reject) => {
const url = payload.SubscribeURL
request(url, (error, response) => {
if (!error && response.statusCode == 200) {
console.log('Yess! We have accepted the confirmation from AWS')
return resolve()
} else {
return reject()
}
})
})
promise.then(() => {
res.end("ok")
})
}
})
})
app.listen(80, process.env.IP, function(request, response){
console.log("## SERVER STARTED ##");
});
I had to remove my port number from the endpoint when calling sns.subscribe! My subscription has now been confirmed :D The new endpoint looks like this.
Endpoint: 'http://ec2-xx-xx-xx-xxx.myregion.compute.amazonaws.com/

Node.js HTTP Server Routing

below node.js code is using express to route to different urls, how can I do the same with http instead of express?
var express = require('express');
var app = express();
app.use(express.static('public'));
app.get('/', function (req, res) {
res.send('Welcome Home');
});
app.get('/tcs', function (req, res) {
res.send('HI RCSer');
});
// Handle 404 - Keep this as a last route
app.use(function(req, res, next) {
res.status(404);
res.send('404: File Not Found');
});
app.listen(8080, function () {
console.log('Example app listening on port 8080!');
});
Here's a quick example. Obviously, there are many ways of doing this, and this is probably not the most scalable and efficient way, but it will hopefully give you an idea.
const http = require('http');
const fs = require('fs');
const server = http.createServer((req, res) => {
req.on('error', err => {
console.error(err);
// Handle error...
res.statusCode = 400;
res.end('400: Bad Request');
return;
});
res.on('error', err => {
console.error(err);
// Handle error...
});
fs.readFile('./public' + req.url, (err, data) => {
if (err) {
if (req.url === '/' && req.method === 'GET') {
res.end('Welcome Home');
} else if (req.url === '/tcs' && req.method === 'GET') {
res.end('HI RCSer');
} else {
res.statusCode = 404;
res.end('404: File Not Found');
}
} else {
// NOTE: The file name could be parsed to determine the
// appropriate data type to return. This is just a quick
// example.
res.setHeader('Content-Type', 'application/octet-stream');
res.end(data);
}
});
});
server.listen(8080, () => {
console.log('Example app listening on port 8080!');
});
Try the code below . It is a pretty basic example
var http = require('http');
//create a server object:
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'}); // http header
var url = req.url;
if(url ==='/about'){
res.write('<h1>about us page<h1>'); //write a response
res.end(); //end the response
}else if(url ==='/contact'){
res.write('<h1>contact us page<h1>'); //write a response
res.end(); //end the response
}else{
res.write('<h1>Hello World!<h1>'); //write a response
res.end(); //end the response
}
}).listen(3000, function(){
console.log("server start at port 3000"); //the server object listens on port 3000
});
express can also be used by http directly.
From: https://expressjs.com/en/4x/api.html#app.listen
The app returned by express() is in fact a JavaScript Function, designed to be passed to Node’s HTTP servers as a callback to handle requests.
var http = require('http')
var express = require('express')
var app = express()
http.createServer(app).listen(80)
With this, you can still make use of express for routing, while keeping native http support.

httpdispatcher returning no or blank response

I have the following simple code for a nodejs server....
var http = require('http');
var port = 1337;
var dispatcher = require('httpdispatcher');
dispatcher.setStaticDirname(__dirname);
dispatcher.setStatic('');
dispatcher.onGet("/page1", function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Page One');
});
var server = http.createServer().listen(port);
server.on('request', function (req, res) {
console.log('GOT');
dispatcher.dispatch(req, res);
});
console.log('Listening on port %s', port);
when I goto http://localhost:1337/index.html it is showing up correctly but when I do http://localhost:1337/page1 nothing happens...how can I get it to function properly...
You need to define your custom dispatcher events, in this case "/page1", before setting the static dispatcher. Otherwise static hogs every possible path remaining to check against the file system.
dispatcher.onGet("/page1", function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Page One');
});
dispatcher.setStaticDirname(__dirname);
dispatcher.setStatic('');
Your revised code will look like this:
var http = require('http');
var port = 1337;
var dispatcher = require('httpdispatcher');
dispatcher.onGet("/page1", function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('Page One');
});
dispatcher.setStaticDirname(__dirname);
dispatcher.setStatic('');
var server = http.createServer().listen(port);
server.on('request', function (req, res) {
console.log('GOT');
dispatcher.dispatch(req, res);
});
console.log('Listening on port %s', port);
Tested and works

Resources