cross-domain fetch() 从页面但不是从开发控制台抛出 "Failed to fetch"
cross-domain fetch() throws "Failed to fetch" from page but not from the dev console
与 相关,但这在开发控制台中似乎也不起作用。
我正在直接从网页访问 restconf 服务器。静态页面由另一台服务器提供。
我正在尝试调用我创建的 RPC,但我怀疑具体细节是否重要 - 这只是一个带有 Authorization
header 的 POST 请求。
我面临的问题是它可以从开发控制台运行,但不能从页面代码运行。
从开发控制台调用它工作正常:
fetch('http://172.17.0.2:8008/restconf/operations/login', {
method: 'POST',
headers: {
accept: 'application/yang-data+json',
authorization: 'Basic '+btoa('admin:admin')
}
})
.then(resp => resp.json())
.then(json => console.log('session token:', json['output']['session-token']))
.then(err => console.error(err));
它输出:
session token: e6cfd60b-f96e-5d8b-b10c-16a5d71a6367
但是从页面上的代码中执行完全相同的调用(上面的逐字副本),它失败了。
请注意 http 请求实际上成功了(开发控制台显示 "status 200 OK"),但是 fetch()
仍然抛出异常(so-very-endearingly-specific TypeError: Failed to fetch
)。
我可以在终端中使用 ngrep
查看请求和响应(出于某种原因开发控制台不会显示 body):
请求和响应如下:
POST /restconf/operations/login HTTP/1.1
Host: 172.17.0.2:8008
Connection: keep-alive
Content-Length: 0
Pragma: no-cache
Cache-Control: no-cache
accept: application/yang-data+json
Origin: http://localhost:5000
authorization: Basic YWRtaW46YWRtaW4=
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36
Referer: http://localhost:5000/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
HTTP/1.1 200 OK
Date: Wed, 22 Jan 2020 11:09:17 GMT
Cache-Control: private, no-cache, must-revalidate, proxy-revalidate
Content-Length: 138
Content-Type: application/yang-data+json
Pragma: no-cache
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Auth-Token
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
Access-Control-Allow-Origin: http://localhost:5000
Content-Security-Policy: default-src 'self'; block-all-mixed-content; base-uri 'self'; frame-ancestors 'none';
Strict-Transport-Security: max-age=15552000; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
{
"output": {
"session-token": "e6cfd60b-f96e-5d8b-b10c-16a5d71a6367",
"expires": "2020-01-22T15:09:17.491906"
}
}
(为简洁起见,省略了 OPTIONS
请求和响应。这并不令人兴奋,据我了解,如果 OPTIONS
未通过验证,则永远不会发送 POST
)
除了时间戳之外,这两种情况下的请求和响应都是相同的。
所以我假设浏览器在页面案例中执行了一些验证,而开发控制台不会进行这些验证。但是什么?
我在某处读到 allow-origin header 在某些情况下不允许是星号,我以前使用过。将它更改为实际的 URL 并没有改变任何东西。
非常感谢您的想法!
现在是"solved"。
原来信息丰富的 Failed to fetch
,实际上是想说 Request aborted by leaving page
。如果只是这么说,就可以避免很多令人头疼的事情了。
所以是的,问题是 fetch()
位于此 Q 的中心被调用以响应单击 form
中的 submit
按钮,但该按钮是错误的设置为在提交时不重新加载页面。因此,当页面重新加载时,挂起的请求被中止,抛出 Failed to fetch
.
我正在使用 Svelte,我并不完全熟悉它,并且在提交时禁用页面重新加载有点不明显。至少如果你已经熟悉这样做的经典方法(即 return false
)。
除了这个错误之外,我还通过在开发控制台中启用 "Preserve log" 来欺骗自己,并认为它在页面重新加载时输出的消息 "Navigated to ..." 是因为我稍后的代码链条(我是 "getting to later"...)。
与
我正在直接从网页访问 restconf 服务器。静态页面由另一台服务器提供。
我正在尝试调用我创建的 RPC,但我怀疑具体细节是否重要 - 这只是一个带有 Authorization
header 的 POST 请求。
我面临的问题是它可以从开发控制台运行,但不能从页面代码运行。
从开发控制台调用它工作正常:
fetch('http://172.17.0.2:8008/restconf/operations/login', {
method: 'POST',
headers: {
accept: 'application/yang-data+json',
authorization: 'Basic '+btoa('admin:admin')
}
})
.then(resp => resp.json())
.then(json => console.log('session token:', json['output']['session-token']))
.then(err => console.error(err));
它输出:
session token: e6cfd60b-f96e-5d8b-b10c-16a5d71a6367
但是从页面上的代码中执行完全相同的调用(上面的逐字副本),它失败了。
请注意 http 请求实际上成功了(开发控制台显示 "status 200 OK"),但是 fetch()
仍然抛出异常(so-very-endearingly-specific TypeError: Failed to fetch
)。
我可以在终端中使用 ngrep
查看请求和响应(出于某种原因开发控制台不会显示 body):
请求和响应如下:
POST /restconf/operations/login HTTP/1.1
Host: 172.17.0.2:8008
Connection: keep-alive
Content-Length: 0
Pragma: no-cache
Cache-Control: no-cache
accept: application/yang-data+json
Origin: http://localhost:5000
authorization: Basic YWRtaW46YWRtaW4=
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36
Referer: http://localhost:5000/
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
HTTP/1.1 200 OK
Date: Wed, 22 Jan 2020 11:09:17 GMT
Cache-Control: private, no-cache, must-revalidate, proxy-revalidate
Content-Length: 138
Content-Type: application/yang-data+json
Pragma: no-cache
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization, X-Auth-Token
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
Access-Control-Allow-Origin: http://localhost:5000
Content-Security-Policy: default-src 'self'; block-all-mixed-content; base-uri 'self'; frame-ancestors 'none';
Strict-Transport-Security: max-age=15552000; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
{
"output": {
"session-token": "e6cfd60b-f96e-5d8b-b10c-16a5d71a6367",
"expires": "2020-01-22T15:09:17.491906"
}
}
(为简洁起见,省略了 OPTIONS
请求和响应。这并不令人兴奋,据我了解,如果 OPTIONS
未通过验证,则永远不会发送 POST
)
除了时间戳之外,这两种情况下的请求和响应都是相同的。 所以我假设浏览器在页面案例中执行了一些验证,而开发控制台不会进行这些验证。但是什么?
我在某处读到 allow-origin header 在某些情况下不允许是星号,我以前使用过。将它更改为实际的 URL 并没有改变任何东西。
非常感谢您的想法!
现在是"solved"。
原来信息丰富的 Failed to fetch
,实际上是想说 Request aborted by leaving page
。如果只是这么说,就可以避免很多令人头疼的事情了。
所以是的,问题是 fetch()
位于此 Q 的中心被调用以响应单击 form
中的 submit
按钮,但该按钮是错误的设置为在提交时不重新加载页面。因此,当页面重新加载时,挂起的请求被中止,抛出 Failed to fetch
.
我正在使用 Svelte,我并不完全熟悉它,并且在提交时禁用页面重新加载有点不明显。至少如果你已经熟悉这样做的经典方法(即 return false
)。
除了这个错误之外,我还通过在开发控制台中启用 "Preserve log" 来欺骗自己,并认为它在页面重新加载时输出的消息 "Navigated to ..." 是因为我稍后的代码链条(我是 "getting to later"...)。