1

我们发现 Gingerbread 默认浏览器处理跨域请求的方式与大多数其他浏览器不同。服务器代码适当地响应OPTIONS调用,所有正确的标题访问控制标题和状态代码,并用状态代码和适当的主体200响应调用。服务器是用 Node 编写的,使用 Express,并且出于本测试的目的,它非常小:POST200

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);

当 Gingerbread 浏览器向 /the/route 发出 CORS 请求时,它收到了responseText一个"OK{some:'json object'}". 由于我们使用的是 jQuery,并且Content-Type响应标头是application/json,因此 jQuery 由于无法解析的 json 响应主体而使请求失败。我们测试过的所有其他浏览器都以 响应"{some:'json object'}",并按预期进行解析。

那么“OK”从何而来?

我们进一步简化了服务器,app.router完全忽略了它。也许这就是问题所在。

...
// 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'});
});

这一次,令我们惊讶的是,服务器"{some:'json object'}{some:'json object'}"在 Gingerbread 浏览器和"{some:'json object}"其他所有浏览器上都做出了响应。当然,前者仍然不是有效的 json,所以我们仍然遇到了错误。

这里发生了什么?

4

1 回答 1

1

事实证明,Gingerbread——至少是我们使用的版本——自动连接了OPTIONS请求的响应和POST请求。此外,Express 会自动发送一个"OK"没有特定正文和状态代码的响应正文200

上面的例子让这一点非常明显,但我们并没有把它缩小到那种程度。因此,我们一直在寻找已知工作版本和失败版本之间在标题等方面的最小差异。

于 2013-07-30T00:07:00.580 回答