Gingerbread Browser Cross Domain Response Concatenation Bug

We have discovered that the Gingerbread default browser handles cross-domain requests differently than most other browsers. The server code responds appropriately to the OPTIONS call, with all the right headers access control headers and a 200 status code, and responds to the POST call with a 200 status code and the appropriate body. The server is written in Node, uses Express, and for the purposes of this test, is very minimal:

var express = require('express');
var http = require('http');

var app = express();
var server = http.createServer(app);

// middleware
app.use(express.logger('dev'));
app.use(function(req, res, next) {
  var origin = req.get('origin');
  if (origin) {
    res.header({
      'Access-Control-Allow-Origin': origin,
      'Access-Control-Allow-Methods': 'GET,POST,OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type',
      'Access-Control-Allow-Credentials': true
    });
  }
  if (req.method === "OPTIONS")
    return res.send(200);
  if (req.method !== "GET" && req.method !== "POST")
    return res.send(405);
  next();
});
app.use(express.json());
app.use(app.router);
app.post('/the/route', function(req, res) {
  res.json(200, {some: 'json object'});
});

server.listen(process.env.PORT || 3000);

When the Gingerbread Browser made a CORS request to /the/route, it received a responseText of "OK{some:'json object'}". Since we were using jQuery, and because the Content-Type response header was application/json, jQuery failed the request due to the unparsable json response body. Every other browser we tested it on responded with "{some:'json object'}", and parsed as expected.

So where is the "OK" coming from?

We simplified the server yet further, ignoring app.router in its entirety. Maybe that was the problem.

...
// middleware
app.use(express.logger('dev'));
app.use(function(req, res, next) {
  res.header('Access-Control-Allow-Origin', '*');
  res.header('Access-Control-Allow-Methods', 'GET,POST,OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type');
  res.header('Access-Control-Allow-Credentials', true);
  res.json(200, {some: 'json object'});
});

This time, to our astonishment, the server responded with "{some:'json object'}{some:'json object'}" on the Gingerbread browser, and "{some:'json object}" on every other browser. The former, of course, still isn't valid json, so we still encountered an error.

What's going on here?

As it turns out, Gingerbread--at least the version we were using--automatically concatenated the response of the OPTIONS request and the POST request. Furthermore, Express was automatically sending a body of "OK" for responses without a specific body and the status code 200.

The examples above made this painfully obvious, but we didn't slim it down to that degree. Therefore, we were chasing after the tiniest difference in headers and the like between the known working version and the failing version.