Сделайте так, чтобы клиент REST Node ожидал, что содержимое JSON в UTF-8 позволит избежать ошибки анализа спецификации - PullRequest
1 голос
/ 31 мая 2019

У меня есть приложение Node.js, использующее Node REST Client для отправки HTTP-запроса GET на сервер, нацеленного на файл в формате JSON. Все идет хорошо, когда этот файл закодирован в UTF-8 без спецификации.

Однако приложение вылетает во время вызова client.get, когда целевой кодировкой файла является UTF-8 с спецификацией. Даже когда я обертываю этот вызов в try / catch для предотвращения сбоя и получения ошибки, я получаю следующую трассировку стека:

events.js:188
      throw err;
      ^

Error: Unhandled "error" event. (Error parsing response. response: [{}], error: [SyntaxError: Unexpected token  in JSON at position 0])
    at exports.Client.emit (events.js:186:19)
    at C:\PFD\workspace\web_adherent\dev\eamnh-front\node_modules\node-rest-client\lib\node-rest-client.js:457:57
    at Object.parse (C:\PFD\workspace\web_adherent\dev\eamnh-front\node_modules\node-rest-client\lib\nrc-parser-manager.js:140:17)
    at ConnectManager.handleResponse (C:\PFD\workspace\web_adherent\dev\eamnh-front\node_modules\node-rest-client\lib\node-rest-client.js:538:32)
    at ConnectManager.handleEnd (C:\PFD\workspace\web_adherent\dev\eamnh-front\node_modules\node-rest-client\lib\node-rest-client.js:531:18)
    at IncomingMessage.<anonymous> (C:\PFD\workspace\web_adherent\dev\eamnh-front\node_modules\node-rest-client\lib\node-rest-client.js:678:34)
    at emitNone (events.js:111:20)
    at IncomingMessage.emit (events.js:208:7)
    at endReadableNT (_stream_readable.js:1064:12)
    at _combinedTickCallback (internal/process/next_tick.js:139:11)

То, что блок кода не показывает здесь, что IntelliJ делает, это U + FEFF пробел нулевой ширины без перерывов Кодовая точка Unicode , отмеченная в следующей строке трассировки стека: Error: Unhandled "error" event. (Error parsing response. response: [< X >{}], error: [SyntaxError: Unexpected token < X > in JSON at position 0]). Так что получается, что Клиент пытается прочитать содержимое файла в виде строки Unicode в кодировке String вместо JSON UTF-8 без спецификации. Поэтому он думает, что спецификация - это символ Unicode U + FEFF.

Я искал SO и нашел довольно много вопросов о настройке mimetypes для клиента , но я все еще получаю ошибку. Я также прочитал документацию по node-rest-client, и кажется, что установка парсера ответов был бы подходящим вариантом, но прокрутка до JSON parser показывает, что это то же самое, что и установка миметипов.

Итак, я закончил с этим:

const options ={
    mimetypes:{
        json:["application/json","application/json; charset=utf-8","application/json;charset=utf-8"]
    }
};
const client = new Client(options);

Попытка установить кодировку на UTF-8, но ошибка та же.

Кто-то знает, что я делаю неправильно, или это проблема с Node REST Client?

Спасибо за вашу помощь.

- Править Это мой код для функции запроса GET:

let Client = require('node-rest-client').Client;

const options ={
    mimetypes:{
        json:["application/json","application/json; charset=utf-8","application/json;charset=utf-8"]
    }
};
const client = new Client(options);

// Reads file contents and calls callback function with data
exports.readFromUrl = (req, fileUrl, callback) => {

    client.get(fileUrl, (data, resp) => {

        if (resp.statusCode === 200) {

            callback(data);

        } else {

            callback("");
        }
    }).on('error', (err) => {

        callback("");
    });
};

Окончательное решение:

На тот случай, если кто-то споткнется здесь из-за аналогичной проблемы, я в итоге заменил JSON-анализатор Node REST Client на собственный, который отфильтровывает недопустимые символы для передачи действительного JSON в обратный вызов.

Вот как я это сделал (используя ранее упомянутые документы).

const Client = require('node-rest-client').Client;
const client = new Client();

// Remove existing regular parsers (otherwise JSON parser still gets called first)
client.parsers.clean();

client.parsers.add({
    "name": "cleanInput",
    "isDefault": false,
    "match": function (response) {

        // Match evey response to replace default parser
        return true;
    },
    "parse": function (byteBuffer, nrcEventEmitter, parsedCallback) {

        let parsedData = null;

        try {

            const cleanData = cleanString(byteBuffer.toString());

            parsedData = JSON.parse(cleanData);
            parsedData.parsed = true;

            // Emit custom event
            nrcEventEmitter('parsed', 'Data has been parsed ' + parsedData);

            // Pass parsed data to client request method callback
            parsedCallback(parsedData);

        } catch(err) {

            nrcEventEmitter('error', err);
        }
    }
});

// Only keeps unicode characters with codes lesser than 127 to avoid forbidden characters in JSON
function cleanString(input) {

    let output = "";

    for (let i=0; i < input.length; i++) {

        if (input.charCodeAt(i) < 127) {

            output += input.charAt(i);
        }
    }
    return output;
}

1 Ответ

1 голос
/ 31 мая 2019

https://stackoverflow.com/a/38036753/7316335

Для синтаксических анализаторов JSON указано НЕ принимать метки порядка байтов.

Следовательно, ваш сервер аварийно завершает работу из-за некорректного GET-запроса клиента.

Проблема должна быть решена при обработке вашего запроса GET вашим сервером, а не путем изменения спецификации синтаксического анализатора JSON.

Я бы посоветовал отфильтровать метки порядка байтов во всех GET-запросах перед анализом на сервере.

в экспресс как работает множественный обратный вызов в app.get

Здесь показано, как одно промежуточное ПО может выполнить предварительную фильтрацию тел GET, прежде чем перейти к фактическому обратному вызову для этого пути GET.

...