javascriptnode.jsrestapildapjs

Endless loading of my NodeJS API site, if username doesnt exist on my LDAP Server


im trying to program a RestfulAPI with NodeJS, ExpressJS and LdapJS. I want to do a user profile page where the user is able to see his attributes on the LDAP Server and can change them.

If i enter a valid uid in the Request-URL the server find the user successfully and respond the wanted attributes of that user which can be seen via browser and postman for example. My problem now is, that if the given "uid" respectively the user itself doesn't exist on my LDAP-Server the site keeps loading endlessly and don't put out any error or any kind of response...

Here is my current code:

const express = require('express');
const router = express.Router();

const ldap = require('ldapjs');
const client = ldap.createClient({
    url: 'ldap://ldap.example.de:389',
    timeout: 30000,
    reconnect: true
});

client.bind('cn=readonly,dc=example,dc=de', 'secret', function(err){
    if(err) throw err;
});

router.get('/:username', function(req, res) {
    let opts = {
        scope: 'sub',
        filter: `(uid=${req.params.username})`,
        // attributes: ['givenName', 'sn', 'jpegPhoto', 'mail', 'uid']
        attributes: ['givenName', 'sn', 'mail', 'uid'] //example attributes (not final)
    }

    client.search('ou=User,dc=example,dc=de', opts, function(err, result) {
        if(err) throw err;

        result.on('searchEntry', function(entry){
            res.send(entry.object);
        });

        result.on('searchReference', function(referral) {
            console.log('referral: ' + referral);
        });

        res.on('error', function(err) {
            console.error('error: ' + err.message);
        });

        res.on('end', function(result) {
            console.log('status: ' + result.status);
        });
    });
});

I searched everywhere for a solution or a likely problem but couldn't find anything. So i have to ask you guys ^^ I hope you can help me out

Updated Code with help by Klaycon:

const express = require('express');
const router = express.Router();

const ldap = require('ldapjs');
const client = ldap.createClient({
    url: 'ldap://ldap.example.de:389',
    timeout: 30000,
    reconnect: true
});

client.bind('cn=readonly,dc=example,dc=de', 'secret', function(err){
    if(err) throw err;
});

router.get('/:username', function(req, res) {
    let opts = {
        scope: 'sub',
        filter: `(uid=${req.params.username})`,
        // attributes: ['givenName', 'sn', 'jpegPhoto', 'mail', 'uid']
        attributes: ['givenName', 'sn', 'mail', 'uid'] //example attributes (not final)
    }

    client.search('ou=User,dc=example,dc=de', opts, function(err, result) {
        if(err) throw err;

        result.on('searchEntry', function(entry){
            res.send(entry.object);
        });

        result.on('searchReference', function(referral) {
            console.log('referral: ' + referral);
        });

        result.on('error', function(err) {
            console.error('error: ' + err.message);
        });

        result.on('end', function(resu) {
            console.log('status: ' + resu.status);
            if(resu.status != 0) res.status(404).send("User not found");
        });
    });
});

Solution

  • Per the ldapjs docs:

    Responses from the search method are an EventEmitter where you will get a notification for each searchEntry that comes back from the server. You will additionally be able to listen for a searchReference, error and end event. Note that the error event will only be for client/TCP errors, not LDAP error codes like the other APIs. You'll want to check the LDAP status code (likely for 0) on the end event to assert success.

    If the search does not return results, result will never emit searchEntry but will emit end instead. Right now you only ever call res.send() in the event that the searchEntry event is fired - but what if it never is? You'll need to listen to the end event and handle the case that no result was found, returning a response to the user accordingly. It looks like you tried to do this as your example is very similar to that from the docs, but you at least forgot to change res to result.

    result.on('end', function(result) {
        console.log('status: ' + result.status);
        if(result.status != 0) res.status(404).send({ message: "User not found" }); //customize as needed
    });