Search code examples
javascriptnode.jsexpressradius

node.js and express : how to wait for udp response


I am studying a bit node.js programming here and faced a problem.

When express gets POST request it should make a radius authentication over UDP with dgram module. The response for the Radius authentication comes later on, but the POST request callback has already exit and the req and res variables are lost and the response using same TCP connection can not be done.

If I should wait for the radius response (which is quite fast) how should I do the waiting in node.js & express ?

The code below does the basic POST handing and radius authentication.

Thank you very much for any tips.


    var http = require('http');
    var express = require('express');
    var bodyParser = require('body-parser');
    var radius = require('radius');
    var dgram = require('dgram');

    var radius_secret = 'really_secret';
    var radius_server = '127.0.0.1';
    var radius_port = '1812';

    function handleAuthentication(req, res) {
        console.log("BODY:",req.body);
        var client = dgram.createSocket("udp4");
        var account = req.body.account; 
        var password = req.body.password;
        var packet = {
            code: 'Access-Request',
            secret: radius_secret,
            identifier: 0,
            attributes: [
                ['NAS-IP-Address', radius_server],
                ['User-Name', account + "@exampledomain.something"],
                ['User-Password', password]
            ]
        };

        client.on('error', function(e) {
                throw e;
            });

        client.on('message', function(msg, rinfo) {
            var radius_response = radius.decode({packet: msg, secret: radius_secret});
            console.log(radius_response);
        });

        var encoded = radius.encode(packet);
        client.send(encoded, 0, encoded.length, radius_port, radius_server);
    }

    var app = express();
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false}));

    app.post('/authenticate', function(req, res) {
        // Authenticate against radius server
        handleAuthentication(req, res);

        // The radius response is not received yet, and we will exit the post request
        // here and loose the req and res. 
    });

    var server = http.createServer(app);
    server.listen(80);


Solution

  • You need to respond in the client callbacks. So, for example, to respond after the message:

    client.on('message', function(msg, rinfo) {
         var radius_response = radius.decode({packet: msg, secret: radius_secret});
         console.log(radius_response);
         res.send('somethingCalculatedWithUDPResponse');
     });
    

    And you should handle it similarly in the error callback.

    res and req don't "die" when the function ends, they can still be referenced by the closures passed as callbacks.