Запрос Axios - Gzip-данные из PHP API - PullRequest
0 голосов
/ 04 мая 2019

возможно ли gzcompress данные в PHP, а затем Axios запросить их?

Я пытался сделать это, но продолжаю получать эту ошибку: «Неправильные символы UTF-8, возможно, неправильно закодированы.»

Мой запрос Axios выглядит следующим образом:

axios({
method: 'get',
url: 'https://someapi.com/api/test',
data: { },
config: { headers: { 'Content-Type': 'application/json', 'Accept-Encoding': 'gzip' }}
})
.then(response => {
    response.data.forEach(el => {
        this.transactions.push(JSON.parse(el));
        this.transactionsFull = this.transactions;
    });
    this.loading = false;
    console.log(this.transactions);
})
.catch(e => {
    this.errors.push(e)
})
$result = openssl_decrypt($cipher_text, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $auth_tag);

$json = json_decode($result);
$channel = Channel::where('uuid', $json->payload->authentication->entityId)->first();
$gzencode = gzencode(json_encode(array('transaction' => $json, 'relation' => json_decode($channel))), 8);

Redis::lpush('transactions_gzencode', $gzencode);

$length = 0;
$transactions = Redis::lrange('transactions_gzencode', 0, -1);
foreach($transactions as $item) {
    $length += strlen($item);
}
header('Content-Encoding: gzip');
header('Content-Type: application/json');
header('Content-Length: ' . $length);
return $transactions;

1 Ответ

0 голосов
/ 04 мая 2019

Я считаю, что axios не может распаковать gzip, но браузер должен быть в состоянии сделать это до того, как axios даже коснется ответа. Но для того, чтобы браузер сделал это, вы должны ответить с правильным заголовком http и форматом.

Обратите внимание, что для использования сжатых данных в теле ответа http вы должны использовать gzencode, а не gzcompress, согласно документации php.

Пример PHP:

$compressed = gzencode(json_encode(['test' => 123]));
header('Content-Type: application/json');
header('Content-Encoding: gzip');
header('Content-Length: ' . strlen($compressed));
echo $compressed;

Пример JS:

console.log(await (await fetch('/test')).json());
// {test: 123}

Редактировать

Поскольку вы пытаетесь отправить массив индивидуально сжатых элементов, вы можете вывести данные в виде JSON-массива двоичных сжатых данных в кодировке base64.

Пример использования pako.js для распаковки массива сжатых транзакций, возвращаемых с сервера:

PHP:

$transactions = ['first', 'second', 'third'];
echo json_encode(array_map('base64_encode', array_map('gzencode', $transactions)));

JS:

(async () => {
    const transactions = (await (await fetch('/test')).json())
        .map(atob)
        .map(blob => pako.inflate(blob, { to: 'string' }));

    console.log(transactions);
})();

Обратите внимание, что теперь я не включил заголовки, потому что я просто отправляю обычный кодированный в json массив.

Недостатком этого подхода является то, что сжатие данных не принесет особой пользы, так как оно преобразуется в base64 перед отправкой клиенту. Необходимо кодировать как base64, поскольку в противном случае json_encode попытается обработать двоичные данные как строку, что приведет к ошибкам кодирования строки.

Вы все еще можете сжать результирующую строку в кодировке json перед отправкой клиенту, как это было сделано в предыдущем ответе, но я не уверен, будет ли сжатие достаточно хорошим:

$compressedTransactions = array_map('gzencode', ['first', 'second', 'third']);

$compressed = gzencode(json_encode(array_map('base64_encode', $compressedTransactions)));
header('Content-Type: application/json');
header('Content-Encoding: gzip');
header('Content-Length: ' . strlen($compressed));
echo $compressed;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...