我们发现Gingerbread默认浏览器处理跨域请求的方式与大多数其他浏览器不同。服务器代码适当地响应OPTIONS
呼叫,所有正确的标头访问控制标头和200
状态代码,并以POST
状态响应200
呼叫代码和适当的身体。服务器是用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浏览器向/ route发出CORS请求时,它收到了responseText
"OK{some:'json object'}"
。由于我们使用的是jQuery,并且因为Content-Type
响应头是application/json
,因为json响应体不可解析,jQuery失败了。我们测试的每个其他浏览器都使用"{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,所以我们仍然遇到错误。
这里发生了什么?
答案 0 :(得分:1)
事实证明,Gingerbread - 至少我们使用的版本 - 会自动连接OPTIONS
请求和POST
请求的响应。此外,Express会自动发送"OK"
正文,以便在没有特定正文且状态代码为200
的情况下进行回复。
上面的例子令人痛苦地显而易见,但我们并没有将其缩小到那个程度。因此,我们追逐已知工作版本和失败版本之间标题之类的微小差异。