-
Notifications
You must be signed in to change notification settings - Fork 111
/
Copy pathui-worker-formatters.ts
105 lines (94 loc) · 3.49 KB
/
ui-worker-formatters.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import {
js as beautifyJs,
html as beautifyHtml,
css as beautifyCss
} from 'js-beautify/js/lib/beautifier';
import * as beautifyXml from 'xml-beautifier';
import { Headers } from '../types';
import { bufferToHex, bufferToString, getReadableSize } from '../util/buffer';
import { parseRawProtobuf, extractProtobufFromGrpc } from '../util/protobuf';
const truncationMarker = (size: string) => `\n[-- Truncated to ${size} --]`;
const FIVE_MB = 1024 * 1024 * 5;
export type WorkerFormatterKey = keyof typeof WorkerFormatters;
export function formatBuffer(buffer: ArrayBuffer, format: WorkerFormatterKey, headers?: Headers): string {
return WorkerFormatters[format](Buffer.from(buffer), headers);
}
const prettyProtobufView = (data: any) => JSON.stringify(data, (_key, value) => {
// Buffers have toJSON defined, so arrive here in JSONified form:
if (value.type === 'Buffer' && Array.isArray(value.data)) {
const buffer = Buffer.from(value.data);
return {
"Type": `Buffer (${getReadableSize(buffer)})`,
"As string": bufferToString(buffer, 'detect-encoding'),
"As hex": bufferToHex(buffer)
}
} else {
return value;
}
}, 2);
// A subset of all possible formatters (those allowed by body-formatting), which require
// non-trivial processing, and therefore need to be processed async.
const WorkerFormatters = {
// Poor man's hex editor:
raw: (content: Buffer) => {
// Truncate the content if necessary. Nobody should manually dig
// through more than 5MB of content, and the full content is
// available by downloading the whole body.
const needsTruncation = content.length > FIVE_MB;
if (needsTruncation) {
content = content.slice(0, FIVE_MB)
}
const formattedContent = bufferToHex(content);
if (needsTruncation) {
return formattedContent + truncationMarker("5MB");
} else {
return formattedContent;
}
},
base64: (content: Buffer) => {
const b64 = content.toString('ascii');
return Buffer.from(b64, 'base64').toString('utf8');
},
markdown: (content: Buffer) => {
return content.toString('utf8');
},
yaml: (content: Buffer) => {
return content.toString('utf8');
},
html: (content: Buffer) => {
return beautifyHtml(content.toString('utf8'), {
indent_size: 2
});
},
xml: (content: Buffer) => {
return beautifyXml(content.toString('utf8'), ' ');
},
json: (content: Buffer) => {
const asString = content.toString('utf8');
try {
return JSON.stringify(JSON.parse(asString), null, 2);
} catch (e) {
return asString;
}
},
javascript: (content: Buffer) => {
return beautifyJs(content.toString('utf8'), {
indent_size: 2
});
},
css: (content: Buffer) => {
return beautifyCss(content.toString('utf8'), {
indent_size: 2
});
},
protobuf: (content: Buffer) => {
const data = parseRawProtobuf(content, { prefix: '' });
return prettyProtobufView(data);
},
'grpc-proto': (content: Buffer, headers?: Headers) => {
const protobufMessages = extractProtobufFromGrpc(content, headers ?? {});
let data = protobufMessages.map((msg) => parseRawProtobuf(msg, { prefix: '' }));
if (data.length === 1) data = data[0];
return prettyProtobufView(data);
}
} as const;