Redirect recursion

2014-12-31 2 min read

    I’ve stumbled onto what seems to be a solution without a problem but something that’s been fun to experiment with and might have an actual application. The idea is to replace a recursion step with a URL redirection. In this situation the base case will return a 200 response while the recursive step will do a redirection with a slightly updated URL. The sample node server below uses this idea to handle a three tasks - sum up to n, compute a factorial, and test whether an integer is prime.

    var express  = require('express'),
        port = 4000;
    
    var app = express();
    
    app.get('/sum', function(req, res) {
      var n = parseInt(req.param('n'),10) || 0,
          a = parseInt(req.param('a'),10) || 0;
      if (n === 0) {
          res.status(200).send('Sum: ' + a);
      } else {
          var url = "/sum?n=" + (n-1) + "&a=" + (a+n);
          res.redirect(url);
      }
    });
    
    app.get('/fact', function(req, res) {
      var n = parseInt(req.param('n'),10) || 1,
              a = parseInt(req.param('a'),10) || 1;
      if (n === 1) {
          res.status(200).send('Factorial: ' + a);
      } else {
          var url = "/fact?n=" + (n-1) + "&a=" + (a*n);
          res.redirect(url);
      }
    });
    
    app.get('/isPrime', function(req, res) {
      var n = parseInt(req.param('n'),10),
          f = parseInt(req.param('f'),10) || 2;
      if (f > Math.sqrt(n)) {
          res.status(200).send('Prime');
      } else if (n % f === 0) {
          res.status(200).send('Composite');
      } else {
          res.redirect('/isPrime?n=' + n + '&f=' + (f+1));
      }
    });
    
    app.listen(port);
    console.log('Server started on port ' + port);
    

    The only cases I can think of where it’s even remotely useful is if your servers are behind a CDN and you want to cache every intermediate result without having to write the application logic to do it or you need to reduce the amount of work done by a single HTTP request. It’s just not an efficient approach otherwise - the overhead of making new HTTP connections and handling arguments for every recursive step is usually more expensive than doing the actual logic within a single request.

    The other use case I can think of is purely educational - it forces you to write your recursive code in a tail recursive style and forces you to think about the state you need to share between redirect requests. And if you’re ever told to solve a problem without using for loops or recursion you can violate the spirit of the request by using a series of HTTP redirects.

    I’m genuinely curious if there’s an actual use case for this and whether anyone’s had to do this.