UnhandledPromiseRejectionWarning: FetchError: недопустимое тело ответа json в - PullRequest
0 голосов
/ 10 ноября 2019

Ошибка: я получаю:

UnhandledPromiseRejectionWarning: FetchError: invalid json response body at {url}
reason: Unexpected token < in JSON at position 0

мой код:

const fetch = require('node-fetch');

const url = 'Reeeealy long url here';

fetch(url)
  .then(res => res.json())
  .then(console.log);

Дело в том, что если URL длиннее ~ 8k + символов, API возвращает

400 Bad Request
Request Header Or Cookie Too Large
nginx

очевидно, яне контролируйте этот API.

что я могу сделать, чтобы предотвратить это?

структура URL:

1) домен

2) версия API

3) конечная точка

4) материал запроса (самая длинная часть)

5) идентификатор в конце

выглядит следующим образом: https://example.com/v1/endpoint/query?query=long_part_here&ids=2145132,532532,535

1 Ответ

0 голосов
/ 10 ноября 2019

Звучит как плохо разработанный API, если ожидается, что long_part очень длинный. Вместо запроса GET он должен использовать POST, чтобы длинный набор данных мог быть отправлен в объекте body. Можете ли вы увидеть, разрешает ли API POST-версию конечной точки, которая позволяет это?

Если нет POST, и вы не контролируете API, у вас не так много вариантов. Единственное, о чем я могу думать, это то, что вы разбиваете свой запрос на несколько отдельных вызовов конечной точки (возможно, по одному на id), если это возможно и приведет к более коротким url размерам на запрос.

Несколько вызовов

Если вы можете выполнять несколько небольших запросов, код может выглядеть следующим образом:

const urls = ["firstUrl","secondUrl","nthUrl"];
let combined = {};
for (const url of urls) {
  fetch(url)
    .then(res => res.json())
    .then(json => combined = {...combined, ...json};
}
console.log(combined);

Это предполагает, что разумно объединить результаты всех в один объект. Если они должны быть различны, вы можете изменить последний then следующим образом:

.then(json => combined = {...combined, {`url${count}`: json}};

, где count - это целое число, которое вы увеличиваете каждый раз, а combined будет выглядеть как

{url1: {/*json from url1*/}, url2: {/*json from url2*/}, ...}

Обработка ошибок

Чтобы обработать ошибку более корректно, вы должны проверить результат, прежде чем предположить, что он возвращен JSON. Вы получили JSON ошибку разбора, потому что возвращенные данные не были JSON. Это был HTML, поэтому он провалился, когда начал с <. Вы могли бы сделать что-то вроде этого:

fetch(url)
  .then(res => {
    if (res.resultCode == "200") return res.json();
    return Promise.reject(`Bad call: ${res.resultCode}`);
  })
  .then(console.log);
...