междоменная функция fetch () выдает «Не удалось получить» со страницы, но не из консоли разработчика - PullRequest
1 голос
/ 22 января 2020

Относится к Получение "TypeError: не удалось получить", когда запрос на самом деле не завершился , но, похоже, это также не работает в консоли разработчика.

I ' Доступ к серверу restconf напрямую с веб-страницы. Stati c страницы обслуживаются с другого сервера.

Я пытаюсь вызвать RP C, который я сделал, хотя я сомневаюсь, что детализация c имеет значение - это просто запрос POST с заголовок Authorization.

Проблема, с которой я сталкиваюсь, заключается в том, что она работает из консоли разработчика, а не из кода страницы.

Вызов этого из консоли разработчика работает нормально:

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 на самом деле завершается успешно (dev console говорит "status 200 OK"), но fetch() по-прежнему выдает исключение (так очень-очень мило) c TypeError: Failed to fetch).

Я вижу запросы и ответы используя ngrep в терминале (по какой-то причине консоль разработчика не отображает тело):

Вот запрос и ответ:

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 запрос и ответ опущены для краткости. Это не очень интересно, и, насколько я понимаю, POST никогда не отправляется, если OPTIONS не проходит проверку)

И запрос, и ответ в обоих случаях идентичны, кроме отметок времени. Поэтому я предполагаю, что браузер выполнил некоторую проверку в случае страницы, чего не происходит с консоли разработчика. Но что?

Я где-то читал, что заголовок allow-origin в некоторых случаях не может быть звездочкой, которую я использовал ранее. Изменение фактического URL ничего не изменило.

Идеи очень ценятся!

1 Ответ

1 голос
/ 06 февраля 2020

Это теперь "решено".

Оказывается, информативно Failed to fetch, действительно пытался сказать Request aborted by leaving page. Если бы он просто сказал это, можно было бы избежать множества царапин на голове.

Так что да, проблема заключалась в том, что fetch(), находящийся в центре этого Q, вызывался в ответ на нажав кнопку submit в form, который был неправильно настроен, чтобы не перезагружать страницу при отправке. Таким образом, когда страница была перезагружена, ожидающие запросы были прерваны, выбрасывая Failed to fetch.

Я использую Svelte, с которым я не совсем знаком, и отключение перезагрузки страницы при отправке - это не -obvious. По крайней мере, если вы уже знакомы с классическим c способом сделать это (то есть return false).

В дополнение к этой ошибке я также обманул себя, включив «Сохранить журнал» в dev console и думал, что сообщение «Navigated to ...», которое он выводит при перезагрузке страницы, было из-за моего кода позже в цепочке (который я «получал позже» ...).

...