node.jsexpressnode.js-connect

Connect.js middleware to rewrite request body


I have an Express-based Node.js application. I would like to convert line ending characters in my incoming request before the request passes to the rest of my Connect middleware stack (specifically, convert all LF characters to CRLF characters). Is there an existing Connect.js middleware for rewriting the request body? Ideally, I'd like to be able to do something like the following:

var rewriter = bodyRewriter(function(bodyString){
   return bodyString.replace(/\n/g, "\r\n");
});
app.use(rewriter); 

I've looked through this list of middleware but couldn't find anything that works. There's connect-modrewrite but it seems to work only for URLs, and not for request bodies; There's connect-injector but it only works for responses, not requests. I am very new to Node.js and would really like to avoid reinventing the wheel for this seemingly straightforward task... is there anything out there that I can use?


Solution

  • This might do the trick:

    var rewriter = function(req, res, next) {
      req.bodyString = '';
      req.on('data', function(chunk) {
        req.bodyString += chunk.replace(/\n/g, '\r\n');
      });
      next();
    });
    app.use(rewriter);
    app.use(express.bodyParser());
    

    In your routes, you'll have req.bodyString available.

    However, this isn't going to work for any items that you access through req.body, because bodyParser is unaware of req.bodyString's existence.

    And since bodyParser wants to read the request's body data directly, you'll have to take a different route and implement a middleware that processes req.body items to make the replacement:

    app.use(express.bodyParser());
    app.use(function(req, res, next) {
      for (var key in req.body) {
        req.body[key] = req.body[key].replace(/\n/g, '\r\n');
      }
      next();
    });
    

    EDIT: okay, after reading your comment and some thinking, this seems to work for clients that post their MIME messages with LF only. It's very much a hack though, so there are bound to be big issues with it.

    The following code should be used instead of express.bodyParser():

    app.use(express.json());
    app.use(express.urlencoded());
    app.use(express.multipart({ defer : true }));
    
    app.use(function(req, res, next) {
      req.form.on('error', function(err) {
        console.error('form error', err);
        next();
      });
      req.form.on('end', function() {
        next();
      });
    
      var oldwrite    = req.form.write.bind(req.form);
      req.form.write  = function(buffer) {
        var string = buffer.toString();
        // shortcut: if a message contains `\r\n`, assume it's okay.
        if (string.indexOf('\r\n') === -1) {
          string = string.replace(/\n/g, '\r\n');
        }
        return oldwrite(new Buffer(string));
      };
    });