LdapJS exop Request timeout - node.js

I have an LdapJS server which implements standard operation and an extended operation to check health:
const server = ldap.createServer();
server.exop('healthcheck', (req, res, next) => {
res.end();
console.log('ended');
return next();
});
...
Then I wrote a simple client script to ping healthcheck service:
const { createClient } = require('ldapjs');
const client = createClient({
url: 'ldap://localhost:1389',
timeout: 2000,
connectTimeout: 2000
});
client.exop('healthcheck', (err, value, res) => {
if (err) {
console.log(`ERROR: ${err.message}`);
process.exit(1);
}
else {
console.log(`STATUS: ${res.status}`);
process.exit(0);
}
});
The problem is that the exop is correctly received by server (I can see the log inside its callback), but the client always logs: ERROR: request timeout (client interrupt).
Why the request is not correctly terminated?
EDIT
I wrote a mocha test for the exop and it works. Seems that the problem is related to the standalone call in healthcheck script.
describe('#healthcheck()', function () {
before(function () {
server = createServer();
server.listen(config.get('port'), config.get('host'), () => {});
});
after(function () {
server.close();
});
it('should return status 0', function (done) {
const { createClient } = require('ldapjs');
const client = createClient({
url: 'ldap://localhost:1389',
timeout: 2000,
connectTimeout: 2000
});
client.exop('healthcheck', (err, value, res) => {
should.not.exist(err);
res.status.should.be.equal(0);
client.destroy();
return done();
});
});
});

Related

fastify-request-context is not working for POST API calls

This is my fastify server written in typescript while using the fastify-request-context plugin I am able to access the context of fastify request when I am requesting the resource using the GET method,
But I am not able to access the context of fastify request if I am requesting the resource using POST method
import fastify from 'fastify';
const { fastifyRequestContextPlugin } = require('fastify-request-context');
const server = fastify({
logger: true
});
const preValidationFn = (req, reply, done): any => {
req.requestContext.set('hello', 'hello world');
console.log(req.requestContext.get('hello'));
done();
};
const handlerFn = (req, reply): any => {
console.log(req.requestContext.get('hello'));
reply.send('hello world');
};
server.route({
url: '/test',
method: ['GET', 'POST'],
preValidation: preValidationFn,
handler: handlerFn
});
server.register(fastifyRequestContextPlugin);
console.log('Starting fastify Typescript server ');
server.listen(8085, '0.0.0.0', (err, address): void => {
if (err) {
console.warn(err);
process.exit(1);
}
console.info(`Server listening at ${address}`);
});
process.on('uncaughtException', error => {
console.error(error);
});
process.on('unhandledRejection', error => {
console.error(error);
});```

How to stop Apollo-Server

I am starting apollo-server with unittests and would like to gracefully stop the server, but in unit tests I get Error: listen EADDRINUSE: address already in use :::4000 (and Mocha's done() called multiple times)
Here the start and stop functions:
let apollo_server = null;
exports.start = function(options, callback) {
options.schema = schema
options.formatError = (error) => {
console.log('Fail to start graphql server', error);
return error;
}
apollo_server = new ApolloServer(options);
apollo_server.listen().then(({ url, subscriptionsUrl }) => {
console.log('Grapql server started.', url, subscriptionsUrl);
});
callback();
}
exports.stop = function(callback) {
apollo_server.stop().then(()=>{
console.log("server stopped")l
callback();
})
}
Testing is done with Apollo-link, apollo-links-ws and subscriptions-transport-ws. It starts with following config to access graphql server>
const serverConfig = { serverUrl: 'http://localhost:4000/', subscriptionUrl: 'ws://localhost:4000/graphql' };
The test looks like following:
describe('Start query', function() {
before('Start the graphql server', function(callback) {
const options = { playground: false };
graphql_server.start(options, callback);
});
before('Create owner', function(callback) {
datasource.new_owner({ name: "test1" })
callback()
});
it('Should return created entry of a query', (callback) => {
owner_query.variables = { id: '4711' }
execute(link, owner_query).subscribe({
next: ({ data }) => {
expect(data.owners.length).to.be.equal(1)
callback()
},
error: error => { expect(error).to.be.null },
complete: () => {},
});
})
after('Stop server', function(callback) {
graphql_server.stop((data) => {
console.log("stop1", data)
callback()
})
})
})
This is the second test. The first is similar for a mutation and is does not throw an error. The second test case ends with error on listen EADDRINUSE of port 4000.
What do I miss?

How can I make my Hapi route wait for data before returning a value?

I am using Hapi.js and have a route that I want to use to fetch data and then return a result.
I have tried to use async/await, but I must be doing something wrong because while the function I am calling eventually prints a result to the console, the route is returning without waiting for that function to return a value.
'use strict';
const Hapi = require('#hapi/hapi');
const HandyStorage = require('handy-storage');
var ethBalance ='';
// Connection to public blockchain via Infura.io
const Web3 = require("web3");
const web3 = new Web3(new Web3.providers.HttpProvider("https://mainnet.infura.io/v3/cf44bc52af3743bcad5f0b66813f8740"));
// Initialize Handy Storage
const storage = new HandyStorage({
beautify: true
});
//Get ETH address from Handy Storage
storage.connect('./preferences.json');
var walletAddress = storage.state.wallet;
// Get wallet balance
const getWalletBalance = async () => {
web3.eth.getBalance(`${walletAddress}`, async function(err, result) {
if (err) {
console.log('There was an error: ' + err);
return ({ error: 'The wallet balance call failed.' });
} else {
ethBalance = await web3.utils.fromWei(result, "ether");
console.log("This should be first: The wallet balance via API call is " + ethBalance + " ETH.");
return ethBalance; // I expect the walletbalance route to wait for this to be returned
}
});
};
// API Server
const init = async () => {
// Connection settings
const server = Hapi.server({
port: 3000,
host: 'localhost'
});
// Get wallet balance
server.route({
method: 'GET',
path: '/walletbalance/',
handler: async (request, h) => {
let result = null;
try {
result = await getWalletBalance();
console.log('This should be second, after the getWalletBalance function has printed to the console.'); // this prints first, so await isn't working as expected
return ({ ethBalance: result });
} catch (err) {
console.log('Error in walletbalance route');
}
}
});
// 404 error handling
server.route({
method: '*',
path: '/{any*}',
handler: function (request, h) {
return ({
message: 'Error!'
});
}
});
await server.start();
console.log('Server running on %s', server.info.uri);
};
process.on('unhandledRejection', (err) => {
console.log(err);
process.exit(1);
});
init();
Any idea where I have gone wrong here? This is the first time I have used async/await.
ETA: My console looks like this:
[nodemon] starting `node index.js`
Server running on http://localhost:3000
This should be second, after the getWalletBalance function has printed to the console.
This should be first: The wallet balance via API call is 4061.894069996147660079 ETH.
And this is the JSON I get back when I use the wallet balance route:
{}
Based on the answer I was given, I was able to get the results I wanted with this:
'use strict';
const Hapi = require('#hapi/hapi');
const HandyStorage = require('handy-storage');
var ethBalance ='';
// Connection to public blockchain via Infura.io
const Web3 = require("web3");
const web3 = new Web3(new Web3.providers.HttpProvider("https://mainnet.infura.io/v3/cf44bc52af3743bcad5f0b66813f8740"));
// Initialize Handy Storage
const storage = new HandyStorage({
beautify: true
});
//Get ETH address from Handy Storage
storage.connect('./preferences.json');
var walletAddress = storage.state.wallet;
// Get wallet balance
async function getWalletBalance(){
let ethBalance = await web3.eth.getBalance(`${walletAddress}`);
if (ethBalance.err) {
console.log('error in the called function');
} else {
return ethBalance;
}
}
// API Server
const init = async () => {
// Connection settings
const server = Hapi.server({
port: 3000,
host: 'localhost'
});
// Get wallet balance
server.route({
method: 'GET',
path: '/walletbalance/',
handler: async (request, h) => {
try {
const result = await getWalletBalance();
const ethBalanceInWei = web3.utils.fromWei(result, "ether");
return ({ balance: ethBalanceInWei });
} catch (err) {
console.log('Error in walletbalance route');
}
}
});
// 404 error handling
server.route({
method: '*',
path: '/{any*}',
handler: function (request, h) {
return ({
message: 'Error!'
});
}
});
await server.start();
console.log('Server running on %s', server.info.uri);
};
process.on('unhandledRejection', (err) => {
console.log(err);
process.exit(1);
});
init();
Thank you for the help! That got me going in the right direction.
Basically your getWalletBalance function is using multiple concepts. callback style functions and inside that you are using await. I have restructured your code a little bit. Hopefully that should fix the issue which you are facing.
'use strict';
const Hapi = require('#hapi/hapi');
const HandyStorage = require('handy-storage');
var ethBalance ='';
// Connection to public blockchain via Infura.io
const Web3 = require("web3");
const web3 = new Web3(new Web3.providers.HttpProvider("https://mainnet.infura.io/v3/cf44bc52af3743bcad5f0b66813f8740"));
// Initialize Handy Storage
const storage = new HandyStorage({
beautify: true
});
//Get ETH address from Handy Storage
storage.connect('./preferences.json');
var walletAddress = storage.state.wallet;
function getWalletBalance() {
return Promise((resolve, reject) => {
web3.eth.getBalance(`${walletAddress}`, (err, result) => {
if (err) {
console.log('There was an error: ' + err);
reject({ error: 'The wallet balance call failed.' });
} else {
resolve(result);
}
});
});
}
// API Server
const init = async () => {
// Connection settings
const server = Hapi.server({
port: 3000,
host: 'localhost'
});
// Get wallet balance
server.route({
method: 'GET',
path: '/walletbalance/',
handler: async (request, h) => {
try {
const result = await getWalletBalance();
ethBalance = await web3.utils.fromWei(result, "ether");
return ethBalance;
} catch (err) {
console.log('Error in walletbalance route');
}
}
});
// 404 error handling
server.route({
method: '*',
path: '/{any*}',
handler: function (request, h) {
return ({
message: 'Error!'
});
}
});
await server.start();
console.log('Server running on %s', server.info.uri);
};
process.on('unhandledRejection', (err) => {
console.log(err);
process.exit(1);
});
init();

Getting error of timeout exceed in mocha

mocha error: timeout of 2000ms exceeded, for async test and hooks ensure the done() callback is being called in this test. if returning a promise, ensure it resolves.
This is what the error i am getting while trying to get response,
This is my index.js file where i export function
exports.info = function(callback) {
var https = require('https');
var options = {
host: 'api.github.com',
path: '/repos/sayanee/build-podcast',
method: 'GET',
headers: { 'User-Agent': 'sayanee' } };
var str = '';
https.request(options, function(response) {
response.on('data', function(data) {
str += data;
});
response.on('end', function() {
callback(JSON.parse(str));
})
response.on('error', function(error) {
console.log(error);
callback();
})
}) .end();
}
This is my indexfile where i describe the test cases
function asyncFunction() {
return new Promise(resolve => {
setTimeout(resolve, 5000);
});
}
describe('Github info', function() {
it.only('returns repo info from github', async function() {
//this.timeout(5000);
await asyncFunction();
word.info(function(reply) {
console.log("er")
expect(reply.language).to.equal('JavaScript');
expect(reply.watchers).to.equal(157);
console.log('RECEIVED');
});
console.log('HELLO'); })
});
Mocha support async test also by passing done callback as param to it that you need to call at test end
describe("Github info", function () {
it.only("returns repo info from github", function (done) {
// set long timeout to be sure word.info finish
this.timeout(5000);
word.info(function (reply) {
console.log("er");
expect(reply.language).to.equal("JavaScript");
expect(reply.watchers).to.equal(157);
console.log("RECEIVED");
// call done at end
done();
});
console.log("HELLO");
});
});
The response is in your question. Mocha is setted up to timeout after 2 second.
Either you makes your request to finish within 2000ms
Either you increase the Mocha timeout, example :
mocha -t 300000
EDIT :
You cannot use async/await mixed up with callbacks
// Wrap your function into a promise
wordInfoPromise() {
return new Promise((resolve, reject) => {
word.info((ret) => {
if (!ret) return reject();
return resolve(ret);
});
});
}
it('returns repo info from github', async function() {
//this.timeout(5000);
await asyncFunction();
const reply = await wordInfoPromise();
console.log("er")
expect(reply.language).to.equal('JavaScript');
expect(reply.watchers).to.equal(157);
console.log('RECEIVED');
console.log('HELLO'); })
});
EDIT 2 :
const req = https.request(options, (res) => {
res.on('data', (d) => {
str += data;
});
res.on('end', () => {
resolve(str);
});
});
req.on('error', (e) => {
reject();
});
req.end();

Disabling console logging with http.get

I have this code:
var should = require('should'),
http = require('http'),
apis = {
baseUrl: 'http://11.0.0.20:4000',
listLiveMatches: '/api/blah/'
};
describe('GET ' + apis.baseUrl + apis.listLiveMatches, function () {
'use strict';
var liveListUrl = apis.baseUrl + apis.listLiveMatches;
it('is alive & returning 200', function (done) {
http.get(liveListUrl, function (res) {
res.should.be.ok;
res.should.have.property('statusCode');
res.statusCode.should.equal(200);
done();
});
});
it('is emitting json response', function (done) {
http.get(liveListUrl, function (res) {
res.should.be.ok;
res.should.have.property('headers');
res.headers['content-type'].should.startWith('application/json');
done();
});
});
});
My gulp task looks like this:
gulp.task('test-server', function () {
return gulp.src('test/rest-api.js')
.pipe(mocha({
reporter: 'spec'
}))
.on('error', function(){
console.log('error');
});
});
My only issue is that with every http.get, the console gets the body of the response logged which I want to prevent, google searches for disabling logging on http.get have yielded nothing.

Resources