From 10d7c288f57e85ca5e17f456b83f4e1409cbebd3 Mon Sep 17 00:00:00 2001 From: Dallas Gutauckis Date: Fri, 16 Dec 2022 02:39:49 -0800 Subject: [PATCH] Adding Brotli compression support (#4288) Summary: Closes https://github.com/facebook/flipper/issues/2578 Adds Brotli compression support for br-encoded endpoints ## Changelog - Brotli compression support Pull Request resolved: https://github.com/facebook/flipper/pull/4288 Test Plan: Confirmed `content-encoding` had `br` for Brotli and that the response text post-decompression was parsed properly: ![image](https://user-images.githubusercontent.com/117083/199068874-1577577f-2d2f-4687-a3d8-aa41a032ab32.png) ![image](https://user-images.githubusercontent.com/117083/199069109-8564ea03-99db-4c8a-9dbc-4d007fe38f5b.png) A note for reviewer(s) is that I am by no means a javascript/typescript/yarn/npm/electron/etc developer, so please please make sure I did things properly and let me know what to fix, how, why it's wrong. Thanks! Reviewed By: antonk52 Differential Revision: D41444623 Pulled By: mweststrate fbshipit-source-id: ac4e84b4501c67a4b89163c20c63de1be14d6cef --- desktop/plugins/public/network/package.json | 2 + desktop/plugins/public/network/utils.tsx | 46 +++++++++++++-------- desktop/plugins/public/yarn.lock | 19 +++++++++ 3 files changed, 50 insertions(+), 17 deletions(-) diff --git a/desktop/plugins/public/network/package.json b/desktop/plugins/public/network/package.json index 9807b1629..dc04dd17a 100644 --- a/desktop/plugins/public/network/package.json +++ b/desktop/plugins/public/network/package.json @@ -16,6 +16,7 @@ "url": "https://github.com/facebook/flipper/issues" }, "dependencies": { + "brotli": "^1.3.3", "lodash": "^4.17.21", "pako": "^2.0.3", "protobufjs": "^6.10.2", @@ -26,6 +27,7 @@ "flipper-plugin": "*" }, "devDependencies": { + "@types/brotli": "^1.3.1", "@types/pako": "^1.0.1", "js-base64": "^3.6.0" } diff --git a/desktop/plugins/public/network/utils.tsx b/desktop/plugins/public/network/utils.tsx index 8ddc9953b..c3638becc 100644 --- a/desktop/plugins/public/network/utils.tsx +++ b/desktop/plugins/public/network/utils.tsx @@ -7,6 +7,7 @@ * @format */ +import decompress from 'brotli/decompress'; import pako from 'pako'; import {Request, Header, ResponseInfo} from './types'; import {Base64} from 'js-base64'; @@ -99,26 +100,37 @@ export function decodeBody( } try { - const isGzip = getHeaderValue(headers, 'Content-Encoding') === 'gzip'; - if (isGzip) { - try { - // The request is gzipped, so convert the raw bytes back to base64 first. - const dataArr = Base64.toUint8Array(data); - // then inflate. - return isTextual(headers, dataArr) - ? // pako will detect the BOM headers and return a proper utf-8 string right away - pako.inflate(dataArr, {to: 'string'}) - : pako.inflate(dataArr); - } catch (e) { - // on iOS, the stream send to flipper is already inflated, so the content-encoding will not - // match the actual data anymore, and we should skip inflating. - // In that case, we intentionally fall-through - if (!('' + e).includes('incorrect header check')) { - throw e; + const contentEncoding = getHeaderValue(headers, 'Content-Encoding'); + switch (contentEncoding) { + // Gzip encoding + case 'gzip': { + try { + // The request is gzipped, so convert the raw bytes back to base64 first. + const dataArr = Base64.toUint8Array(data); + // then inflate. + return isTextual(headers, dataArr) + ? // pako will detect the BOM headers and return a proper utf-8 string right away + pako.inflate(dataArr, {to: 'string'}) + : pako.inflate(dataArr); + } catch (e) { + // on iOS, the stream send to flipper is already inflated, so the content-encoding will not + // match the actual data anymore, and we should skip inflating. + // In that case, we intentionally fall-through + if (!('' + e).includes('incorrect header check')) { + throw e; + } + break; } } + + // Brotli encoding (https://github.com/facebook/flipper/issues/2578) + case 'br': { + return new TextDecoder().decode( + decompress(Buffer.from(Base64.toUint8Array(data))), + ); + } } - // If this is not a gzipped request, assume we are interested in a proper utf-8 string. + // If this is not a gzipped or brotli-encoded request, assume we are interested in a proper utf-8 string. // - If the raw binary data in is needed, in base64 form, use data directly // - either directly use data (for example) const bytes = Base64.toUint8Array(data); diff --git a/desktop/plugins/public/yarn.lock b/desktop/plugins/public/yarn.lock index 573cd4398..0fb1f5e33 100644 --- a/desktop/plugins/public/yarn.lock +++ b/desktop/plugins/public/yarn.lock @@ -175,6 +175,13 @@ resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0" integrity sha512-iIgQNzCm0v7QMhhe4Jjn9uRh+I6GoPmt03CbEtwx3ao8/EfoQcmgtqH4vQ5Db/lxiIGaWDv6nwvunuh0RyX0+A== +"@types/brotli@^1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@types/brotli/-/brotli-1.3.1.tgz#65dc6c69bb9f4159677032f60e81ffc09faf1fce" + integrity sha512-mGwX0BBQqmpHoX8+b8Oez0X+ZEYnl2gbDL2n0HxYT4imqhTChhj1AAgAKVWNZSuPvXGZXqVoOtBS0071tN6Tkw== + dependencies: + "@types/node" "*" + "@types/d3-path@^1": version "1.0.9" resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-1.0.9.tgz#73526b150d14cd96e701597cbf346cfd1fd4a58c" @@ -385,6 +392,11 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= +base64-js@^1.1.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" @@ -422,6 +434,13 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" +brotli@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/brotli/-/brotli-1.3.3.tgz#7365d8cc00f12cf765d2b2c898716bcf4b604d48" + integrity sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg== + dependencies: + base64-js "^1.1.2" + builtin-modules@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887"