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
This commit is contained in:
Dallas Gutauckis
2022-12-16 02:39:49 -08:00
committed by Facebook GitHub Bot
parent a4525790a2
commit 10d7c288f5
3 changed files with 50 additions and 17 deletions

View File

@@ -16,6 +16,7 @@
"url": "https://github.com/facebook/flipper/issues" "url": "https://github.com/facebook/flipper/issues"
}, },
"dependencies": { "dependencies": {
"brotli": "^1.3.3",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"pako": "^2.0.3", "pako": "^2.0.3",
"protobufjs": "^6.10.2", "protobufjs": "^6.10.2",
@@ -26,6 +27,7 @@
"flipper-plugin": "*" "flipper-plugin": "*"
}, },
"devDependencies": { "devDependencies": {
"@types/brotli": "^1.3.1",
"@types/pako": "^1.0.1", "@types/pako": "^1.0.1",
"js-base64": "^3.6.0" "js-base64": "^3.6.0"
} }

View File

@@ -7,6 +7,7 @@
* @format * @format
*/ */
import decompress from 'brotli/decompress';
import pako from 'pako'; import pako from 'pako';
import {Request, Header, ResponseInfo} from './types'; import {Request, Header, ResponseInfo} from './types';
import {Base64} from 'js-base64'; import {Base64} from 'js-base64';
@@ -99,26 +100,37 @@ export function decodeBody(
} }
try { try {
const isGzip = getHeaderValue(headers, 'Content-Encoding') === 'gzip'; const contentEncoding = getHeaderValue(headers, 'Content-Encoding');
if (isGzip) { switch (contentEncoding) {
try { // Gzip encoding
// The request is gzipped, so convert the raw bytes back to base64 first. case 'gzip': {
const dataArr = Base64.toUint8Array(data); try {
// then inflate. // The request is gzipped, so convert the raw bytes back to base64 first.
return isTextual(headers, dataArr) const dataArr = Base64.toUint8Array(data);
? // pako will detect the BOM headers and return a proper utf-8 string right away // then inflate.
pako.inflate(dataArr, {to: 'string'}) return isTextual(headers, dataArr)
: pako.inflate(dataArr); ? // pako will detect the BOM headers and return a proper utf-8 string right away
} catch (e) { pako.inflate(dataArr, {to: 'string'})
// on iOS, the stream send to flipper is already inflated, so the content-encoding will not : pako.inflate(dataArr);
// match the actual data anymore, and we should skip inflating. } catch (e) {
// In that case, we intentionally fall-through // on iOS, the stream send to flipper is already inflated, so the content-encoding will not
if (!('' + e).includes('incorrect header check')) { // match the actual data anymore, and we should skip inflating.
throw e; // 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 // - If the raw binary data in is needed, in base64 form, use data directly
// - either directly use data (for example) // - either directly use data (for example)
const bytes = Base64.toUint8Array(data); const bytes = Base64.toUint8Array(data);

View File

@@ -175,6 +175,13 @@
resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0" resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0"
integrity sha512-iIgQNzCm0v7QMhhe4Jjn9uRh+I6GoPmt03CbEtwx3ao8/EfoQcmgtqH4vQ5Db/lxiIGaWDv6nwvunuh0RyX0+A== 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": "@types/d3-path@^1":
version "1.0.9" version "1.0.9"
resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-1.0.9.tgz#73526b150d14cd96e701597cbf346cfd1fd4a58c" 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" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 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: base@^0.11.1:
version "0.11.2" version "0.11.2"
resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" 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" split-string "^3.0.2"
to-regex "^3.0.1" 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: builtin-modules@^3.1.0:
version "3.2.0" version "3.2.0"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.2.0.tgz#45d5db99e7ee5e6bc4f362e008bf917ab5049887"