Related to Getting "TypeError: failed to fetch" when the request hasn't actually failed, but that didn't seem to work in the dev console either.
I'm accessing a restconf server directly from a web page. Static pages are served from another server.
I'm trying to call an RPC I've made, though I doubt that specific detail matters - it's just a POST request with an Authorization
header.
The problem I'm facing is that it works from the dev console but not from the page code.
Calling this from the dev console works fine:
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));
It outputs:
session token: e6cfd60b-f96e-5d8b-b10c-16a5d71a6367
But doing the exact same call (verbatim copy of the above) from within the code on the page, it fails.
Do note that the http request actually succeeds (dev console says "status 200 OK"), but fetch()
still throws an exception (the so-very-endearingly-specific TypeError: Failed to fetch
).
I can see the requests & responses using ngrep
in a terminal (for some reason the dev console won't display the body):
Here are the request and response:
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"
}
}
(The OPTIONS
request and response omitted for brevity. It's not terribly exciting, and from my understanding the POST
is never sent if the OPTIONS
does not pass validation)
Both request and response in the two cases are identical apart from the time stamps. So I'm assuming there's some validation performed by the browser in the page case that doesn't happen from the dev console. But what?
I read somewhere that the allow-origin header isn't allowed to be an asterisk in some cases, which I was using before. Changing it to the actual URL didn't change anything.
Ideas greatly appreciated!