Gingerbread 浏览器跨域响应连接错误

Posted

技术标签:

【中文标题】Gingerbread 浏览器跨域响应连接错误【英文标题】:Gingerbread Browser Cross Domain Response Concatenation Bug 【发布时间】:2013-07-29 23:10:21 【问题描述】:

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

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"OKsome:'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');
);

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

这是怎么回事?

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

以上是关于Gingerbread 浏览器跨域响应连接错误的主要内容,如果未能解决你的问题,请参考以下文章

Socket.IO 中的跨域连接

宽带连接出错误显示651怎么办

adobe 连接跨域过滤器

苹果电脑safari不能连接服务器

一个页面上面很多iframe会有啥影响?

几种跨域的方法