Im writing some integration tests for a node project.
We need to get reliable metrics about server performance. For that, we want to open a socket between the server and the client before any test is performance, this way, we can eliminate the time needed to create a socket between client and server.
I have created a small test case like this:
'use strict';
var express = require( 'express' ),
net = require('net'),
http = require('http');
var host = 'localhost',
port = 8000;
describe( 'dummy describe', function() {
var app, server, agent, opts;
before( function( done ) {
app = express();
app.get( '/', function( req, res, next ) {
res.send( 'stuff' );
});
server = http.createServer( app );
server.listen( 8000 );
agent = new http.Agent({ maxSockets: 1 });
agent.createConnection({ port: port, host: host }, function() {
return net.createConnection({ port: port, host: host }, function() {
console.log( 'Socket fd open on before block: ' + this._handle.fd );
done();
});
});
opts = {
hostname: host,
port: port,
path: '/',
agent: agent,
method: 'GET',
};
});
it( 'dummy test', function ( done ) {
var req = http.request( opts, function( res ) {
console.log( 'Socket fd used on GET: ' + res.socket._handle.fd );
done();
});
req.end();
});
});
Here, I can see the execution of the before block, where I console.log the socket file descriptor.
Reading node documentation, I figured out that his was the right way to pass a socket to a agent. But its not working, its output different sockets.
I tried a thousands combinations, but got no luck.
I want to manually connect to a socket, and then use it to perform http.request without having to re open a different socket.
What would be the correct way of doing this ?
Related
When in development env, this works as expected,
Server Code... In development, I only specify the url in the client as const socket = io("http://localhost:3001"); Below is the server code.
const httpServer = createServer(app);
export const io = new Server(httpServer, {
cors: {
origin: "*",
},
path: "/socket.io/",
});
io.on("connection", (socket) => {
// make function calls
postOrderDeliveryStatus(socket);
// getOrders(socket);
// console.log("Socket Connected");
// close socket
socket.on("disconnect", () => {
socket.disconnect(true);
});
});
httpServer.listen(3001);
//mongoose
// console.log(process.env.CONNECTION_URL)
mongoose
.connect(process.env.CONNECTION_URL, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
})
.then(() =>
app.listen(PORT, () =>
winston.info(
`Server Running in ${process.env.NODE_ENV} mode on Port: ${PORT}`
)
)
)
.catch((error) => console.log(`${error} did not connect`));
mongoose.set("useFindAndModify", false);
Client...
const socket = io("http://localhost:3001");
const dispatchOrderHandler = () => {
const delivery_status = "DISPATCHED";
socket.emit("update-order", order._id, delivery_status);
// dispatch(getOrderDetailsToProcess(paramsOrderId)); //This dispatch alone can suffice
socket.on("updated-order", (updated_order) => {
dispatch(
getOrderDetailsToProcess(paramsOrderId, (order) => [
...order,
updated_order,
])
);
});
};
The error i get when sockets run is net::ERR_CONNECTION_REFUSED. I also tried
const socket = io(); without specifying the url since both the client and the server run on the same domain but that didn't either? What should the connection URL be in production since specifying the domain name hasn't worked? Am using heroku!
When using a hosting service, the service will provide the port to the client. You can access that port through process.env.PORT. To make the experience a bit more friendly to yourself as a developer, you can listen to the port using httpServer.listen(process.env.PORT || 3001);
As for the client, I believe you are right on using const socket = io();, although I haven't used socket.io in a while.
Use const socket = io("serverurl") to connect to a specific server.
I believe you can specify a port there as well.
So like for my website, I would do: const socket = io("us2.swordbattle.io:3000")
The doubt with with code is two things:
When i send request through a browser, i dont get a console log message as "connected" but if i use http.get() or http.request() , it works fine
2)The "connect" event receives a callback with req,clientSocke,head ! now where can i see the server socket ?
const http=require("http")
const server=http.createServer()
server.on("connect",(req,c_socket,head)=>{
console.log("connected")
})
server.listen(5000,()=>{console.log("server up)})
when you access the server via browser, the method is using GET not CONNECT. That's why console.log does not show.
if you want console.log to show when accessing from the browser, you can use request event.
this is an explanation from node.js docs.
'connect' event is emitted each time a server responds to a request
with a CONNECT method. If this event is not being listened for,
clients receiving a CONNECT method will have their connections closed.
node.js docs
you can make a socket server with a net package with createSever method.
this is an example of how to make a simple request to the socket server.
const http = require('http');
const net = require('net');
const { URL } = require('url');
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('hello world');
});
server.on('connect', (req, clientSocket, head) => {
console.log('connected');
// Connect to an origin server
const { port, hostname } = new URL(`http://${req.url}`);
const serverSocket = net.connect(port || 80, hostname, () => {
clientSocket.write(
'HTTP/1.1 200 Connection Established\r\n' +
'Proxy-agent: Node.js-Proxy\r\n' +
'\r\n'
);
serverSocket.write(head);
serverSocket.pipe(clientSocket);
clientSocket.pipe(serverSocket);
});
});
server.listen(5000, () => {
console.log('server up');
});
// Make a request to a tunneling server
const req = http
.request({
port: 5000,
host: 'localhost',
method: 'CONNECT',
path: 'www.google.com:80',
})
.end();
req.on('connect', (res, socket, head) => {
console.log('got connected!');
// Make a request over an HTTP tunnel
socket.write(
'GET / HTTP/1.1\r\n' +
'Host: www.google.com:80\r\n' +
'Connection: close\r\n' +
'\r\n'
);
socket.on('data', (chunk) => {
console.log(chunk.toString());
});
socket.on('end', () => {
console.log('end');
});
});
I was tried socket connection in AWS EC2 with ssl certified.
i have created key file and also cert file, and attach my key into amazon load balance.
My server side code is
const socket = require( 'socket.io' );
const express = require( 'express' );
const https = require( 'https' );
const fs = require("fs");
var port = 8443;
var options = {
key: fs.readFileSync('/var/www/html/key/my.key').toString(),
cert: fs.readFileSync('/var/www/html/key/my.crt').toString(),
NPNProtocols: ['http/2.0', 'spdy', 'http/1.1', 'http/1.0']
};
var app = express();
var server = https.createServer(options , app);
var io = require('socket.io')(server);
io.sockets.on( 'connection', function( client ) {
console.log( "New client !" );
client.on( 'search_id', function( data ) {
console.log( 'Message received ' + data.search_id );
io.sockets.emit( 'search_id', { search_id: data.search_id } );
});
});
server.listen(8443, function () {
var addr = server.address();
console.log(' server listening on :' + addr.port);
});
My Client side code is
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.js"></script>
var socket = io.connect( 'https://'+window.location.hostname+':8443' );
socket.emit( 'search_id', { search_id: search_id } );
socket.on('connect_error', function(data){
console.log(data);
console.log("Connection Failed");
});
socket.on( 'search_id', function( data ) {
console.log(data);
});
I run my server js in terminal. Initialy returns server listening
Then it goes to connect_error - Connection Failed returns in my console.
My code working in my local system. What mistake i did, Is there any other configuration in AWS server?.
I create a simple http server from which I want do transfer some bytes of data over socket. So i am listening to 'connect' event of the server. But it is never called?
here is my code.
var http = require('http');
var server = http.createServer(function(req, res) {
res.setHeader('Content-type', 'text/html');
res.end('<h3>Yeah! you are connected on ' + Date() + '</h3>');
console.log('User connected');
});
server.on('connect', function(req, socket, head) {
//var addr = socket.remoteAddress;
console.log('IP - ');
});
server.listen(8000);
For connect event, when the server is running, need to make a request to a tunneling proxy.
Replace your server.listen(8000); with this:
server.listen(8000, '127.0.0.1', () => {
// make a request to a tunneling proxy
const options = {
port: 8000,
hostname: '127.0.0.1',
method: 'CONNECT',
path: 'www.google.com:80'
};
const req = http.request(options);
req.end();
});
I have this basic nodejs script:
var express = require('express'),
Sequelize = require('sequelize'),
promise = require('bluebird'),
app = express(),
optimus = new Sequelize('optimus', 'root', 'test', {host: '127.0.0.1', dialect: 'mysql'}),
query = 'SELECT id FROM borrowers LIMIT 0,10',
query2 = 'SELECT COUNT(*) FROM borrowers';
app.get('/', function(req,res) {
var chain = new Sequelize.Utils.QueryChainer();
console.log('begin');
chain.add(optimus, 'query', [query,null,null,[]])
.add(optimus, 'query', [query2,null,null,[]])
.run()
.success(function() {
console.log('done');
}).error(function(err) {
console.log('oh no');
});
console.log('end');
res.send('Hi Ma!');
});
var server = app.listen(3000, function() {
console.log('Listening on port %d', server.address().port);
}
);
Neither 'done' nor 'oh no' ever fires which leads me to believe that I can' chain raw queries in this manner.
What I'd really like to accomplish is to asynchronously resolve both queries and pass the results back via res.send().
I have to admit to being a complete n00b at nodejs so any insights into how to correctly structure this would be greatly appreciated.
The major issue with your code is the fact, that you are sending a response to the client/browser too early. Instead of res.send-ing at the end of the app.get method, you need to send the answer inside the success respectively inside the error callback. Here you are:
var express = require('express'),
Sequelize = require('sequelize'),
promise = require('bluebird'),
app = express(),
optimus = new Sequelize('sequelize_test', 'root', null, {host: '127.0.0.1', dialect: 'mysql'}),
query = 'SELECT id FROM borrowers LIMIT 0,10',
query2 = 'SELECT COUNT(*) as count FROM borrowers';
app.get('/', function(req,res) {
var chain = new Sequelize.Utils.QueryChainer();
console.log('begin');
chain
.add(optimus.query(query, null, { raw: true }))
.add(optimus.query(query2, null, { raw: true, plain: true }))
.run()
.success(function(results) {
res.send({
resultOfQuery1: results[0],
resultOfQuery2: results[1]
});
}).error(function(err) {
console.log('oh no', err);
});
});
var server = app.listen(3000, function() {
console.log('Listening on port %d', server.address().port);
}
);
Please notice, that I changed the credentials to my local ones. Furthermore also check the arguments of chain.add. Instead of passing the values for an upcoming serial executation, we just throw the actual asynchronous methods into it and let the querychainer handle their promises.