摘要
使用相同的代码(在asp.net核心站点中),跨不同的浏览器,当浏览到页面XMLHttpRequest
的localhost IIS版本时,将检测到某种错误并调用其错误事件并将状态设置为零尽管已成功读取了数据(网络显示200 OK)并将其存储在responseText
中。
在生产/登台Web服务器上,每次代码都能正常正常运行。
由于某些原因,纯文本文件似乎在本地也可以正常工作(严格地说,它们是由较早的中间件处理的),但是生成的内容(带有常规标头的HTML和JSON)会产生错误。
我的问题是:为什么以前从未出现过此错误?
下面的答案...
完整原始帖子
直到最近(2-3天前),使用jQuery的$ .get()进行AJAX调用在我的开发机器上以及在暂存/生产环境中均能正常工作。
自昨天(我注意到)以来,AJAX调用现在在站点的本地主机版本上失败,并且在生产版本上可以正常工作。
我在Firefox,Edge和Opera中尝试过-都得到了相同的结果。我生成了可以并且仍然可以产生相同错误结果的最简化的代码-这几乎完全排除了我的代码。
我查看了Firefox和Edge的发行说明,找不到与我相关的任何内容。
本地主机正在使用自签名测试证书,该证书在firefox中具有异常。登台站点具有真实的第三方签名证书。
整个页面代码是:
<html>
<head>
<style>@media print {#ghostery-purple-box {display:none !important}}</style>
</head>
<body>
<h1>hi</h1>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
</body>
</html>
然后,我在每个浏览器的控制台窗口中运行此javascript:
$.ajax({url:'/Test',error:function(a,b,c){alert(b)}, success:function(a){alert(a);}});
请注意格式,单行是为了简化复制/粘贴和测试。
我能想到的每种配置中的输出都是alert(b)
部分被运行,而b
等于“错误”。
两种配置的唯一区别是URL:
https://localhost:44300/Test
vs
https://[productionfqdn]:444/Test
从Web服务器返回的标头,在本地是IIS Express,在远程是IIS-两者均由Kestrel支持,因为它是ASP.NET Core网站的一部分-尽管我排除了其中的任何一个问题(在意识到与我的代码库无关之前,我不会花多少时间回到以前的代码版本。)
IIS Express :(开发)
HTTP/2.0 200 OK
content-type: text/html; charset=utf-8
server: Kestrel
x-sourcefiles: [redacted]
x-powered-by: ASP.NET
date: Tue, 26 Mar 2019 23:05:06 GMT
X-Firefox-Spdy: h2
IIS :(登台)
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Server: Kestrel
Strict-Transport-Security: max-age=2592000
Date: Tue, 26 Mar 2019 23:04:47 GMT
调用本地主机站点的结果是成功的,在FireFox中的devtools中,我可以看到已经返回了预期的数据,在这种情况下,与从/ Test检索到的数据相同,以便在第一个测试中启动测试地方。
在登台站点上进行相同调用的结果将产生警报,并带有html文本。
我希望这两个环境产生相同的结果,即取回html文本。
有什么想法吗?我很困惑!
编辑2019-03-28 我尝试从同一页面的上下文中,使用普通的XMLHttpRquest进行相同的操作,并得到以下信息:
var x = new XMLHttpRequest();
undefined
x.open('GET', '/Test')
undefined
x.send(null)
undefined
x
XMLHttpRequest { onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, responseURL: "", status: 0, statusText: "", responseType: "",
response: "<h1>hi</h1>\r\n<script type=\"text/javascript\" src=\"https://code.jquery.com/jquery-3.3.1.min.js\"></script>"
人们可以在对象的响应字段中清楚地看到来自Web服务器的预期响应。 (为清楚起见,请换行)
与直接来自浏览器devtools的图像相同:
编辑2 2019-03-28
(此外,“网络”标签显示的数据恢复正常)
因此,由于上一次编辑似乎表明jQuery所做的事情很愚蠢,所以我决定运行调试器,看看jQuery中发生了什么。在当前版本(3.3.1)中,我在第9300行中断了,该行是在请求完成后以及jQuery评估完请求后。我发现完成功能似乎在我的本地(dev)和远程(stg)Web服务器之间具有不同的值:
本地
远程
主要问题在于,jQuery的本地版本使用done()
触发到status = 0
,而远程版本使用done()
触发到status = 200
。 / p>
在两个版本中,本地response
变量的状态字段均为'成功'。在9247行上,jQuery正在评估传递给status
的{{1}}变量,并且由于没有传递done()
,因此0
被设置为isSuccess
。
但是,网络显示:
我将继续挖掘,但会注意任何有见地的回答:)
编辑3
因此false
从9538行被调用:
done()
callback = function( type ) {
return function() {
if ( callback ) {
callback = errorCallback = xhr.onload =
xhr.onerror = xhr.onabort = xhr.ontimeout =
xhr.onreadystatechange = null;
if ( type === "abort" ) {
xhr.abort();
} else if ( type === "error" ) {
// Support: IE <=9 only
// On a manual native abort, IE9 throws
// errors on any property access that is not readyState
if ( typeof xhr.status !== "number" ) {
complete( 0, "error" );
} else {
complete(
// File: protocol always yields status 0; see #8605, #14207
xhr.status,
xhr.statusText
);
}
之前的行正在检查if ( typeof xhr.status !== "number" ) {
,这是xhr.status
,而不是实际的状态代码,尽管肯定返回了200。它解释了“错误”消息从何而来!在0
中,它正在检查状态代码:
done()
那0到底是哪里来的?!
编辑4
最终,问题似乎是isSuccess = status >= 200 && status < 300 || status === 304;
从本地主机给我的状态为0,直到几天前才出现。超级沮丧:
XMLHttpRequest
编辑5
因此,再次尝试将其降低到最低要求,以使错误发生。我在jquery中扎根了一下,并注意到XHR正在调用JQ的错误回调(已分配给var x = new XMLHttpRequest(); x.open('GET', 'https://localhost:44300/Test'); x.send(null);
undefined
x
XMLHttpRequest { onreadystatechange: null, readyState: 1, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, responseURL: "",
status: 0, statusText: "", responseType: "", response: "" }
var x = new XMLHttpRequest(); x.open('GET', 'https://127.0.0.1:44300/Test'); x.send(null);
undefined
x
XMLHttpRequest { onreadystatechange: null, readyState: 1, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, responseURL: "",
status: 0, statusText: "", responseType: "", response: "" }
),所以我做了同样的事情:
xhr.onerror
这导致警报显示“发生了错误”,因此我可以肯定地说,它不是jQuery而是某种奇怪的东西在本地引起了错误。
编辑6
将以上内容修改为var x = new XMLHttpRequest()
XMLHttpRequest { onreadystatechange: null, readyState: 0, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, responseURL: "", status: 0, statusText: "", responseType: "", response: "" }
x.onerror = function () {console.log('error happened')};
function onerror()
x.open('GET','/Test')
undefined
x.send(null)
undefined
error happened
x
XMLHttpRequest { onreadystatechange: null, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, responseURL: "", status: 0, statusText: "", responseType: "", response: "<h1>hi</h1>\r\n<script type=\"text/javascript\" src=\"https://code.jquery.com/jquery-3.3.1.js\"></script>" }
以产生错误并得到此消息:
x.onerror = function (e) {console.log('error happened'); console.log(e)};
没有什么亮点。
编辑7
修改我的测试页以使其更全面,以使我可以进行更好的测试:
error
bubbles: false
cancelBubble: false
cancelable: false
composed: false
currentTarget: null
defaultPrevented: false
eventPhase: 0
explicitOriginalTarget: XMLHttpRequest { readyState: 4, timeout: 0, withCredentials: false, … }
isTrusted: true
lengthComputable: false
loaded: 0
originalTarget: XMLHttpRequest { readyState: 4, timeout: 0, withCredentials: false, … }
returnValue: true
srcElement: XMLHttpRequest { readyState: 4, timeout: 0, withCredentials: false, … }
target: XMLHttpRequest { readyState: 4, timeout: 0, withCredentials: false, … }
timeStamp: 594573
total: 0
type: "error"
当我要求<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script type="text/javascript">
var x = new XMLHttpRequest();
$(document).ready(function () {
x.onerror = function (e) { console.log('error happened'); console.log(e); $('#err').text(e); };
x.onreadystatechange = function () {
if (x.readyState == 4) {
$('#test').text(x.responseText);
}
};
//x.open('GET', '/test.txt');
x.open('GET', '/Search/Server?term=[redacted]');
x.send(null);
});
</script>
<h1>hi</h1>
<div style="border: 1px solid black">
<pre id="test"></pre>
</div>
<div style="border: 1px solid red">
<pre id="err"></pre>
</div>
正常时,/test.txt
没有错误
当我索要status = 200
只是我上面的代码/Test
时,会产生错误(没有关于原因的有用信息)
当我请求返回格式正确的json status = 0
的{{1}}时,会产生错误(没有有用的信息)
AJAX标头(有效)
/Search/Server?term=[redacted]
AJAX标头(不起作用)
status = 0
是否可能是HTTP/2.0 304 Not Modified
content-type: text/plain
last-modified: Thu, 28 Mar 2019 06:20:18 GMT
accept-ranges: bytes
etag: "1d4e52e505b3d27"
server: Kestrel
x-sourcefiles: [redacted]
x-powered-by: ASP.NET
date: Thu, 28 Mar 2019 06:47:09 GMT
X-Firefox-Spdy: h2
标头中的HTTP/2.0 200 OK
content-type: text/html; charset=utf-8
server: Kestrel
x-sourcefiles: [redacted]
x-powered-by: ASP.NET
date: Thu, 28 Mar 2019 06:46:18 GMT
X-Firefox-Spdy: h2
HTTP/2.0 200 OK
content-type: application/json; charset=utf-8
server: Kestrel
x-sourcefiles: [redacted]
x-powered-by: ASP.NET
date: Thu, 28 Mar 2019 06:37:41 GMT
X-Firefox-Spdy: h2
?!
值得重申的是,所有这些使用 exact 相同代码的调用在生产/阶段中都可以正常工作-相同的浏览器,相同的身份验证(发生后并不相关),相同的相对URL唯一的区别是prd / stg是IIS,具有真实证书,本地是IIS express,并使用带有异常的自签名。我能想到的。
答案 0 :(得分:0)
事实证明,问题出在自定义的asp.net中间件上,该中间件检查特定条件,然后允许管道继续运行。我认为它在开发中所做的一切都会导致请求中止或质量使其无法正常工作。本质上,问题代码是;
if (env.IsDevelopment())
{
// Unimportant code here
await _next(context);
await Task.CompletedTask; // <<-- this line made it go wrong
}
用“ return”代替问题所在行。
if (env.IsDevelopment())
{
// Unimportant code here
await _next(context);
return;
}
if语句下还有更多工作,如果IsDevelopment() == true
可以跳过,但是我认为我在这里的第一个块中没有正确终止此中间件。
为什么这对XMLHttpRequest
返回了本质上不同的答复,这超出了我的理解。我找不到任何指向不良反应的东西。
静态文件通过AJAX可以正常运行的事实表明,因为它是一个较早的中间件,所以可能是我的自定义中间件出现在了管道的后面。