|
7 | 7 | isProbablyGrpcProto,
|
8 | 8 | isValidGrpcProto,
|
9 | 9 | } from '../../util/protobuf';
|
| 10 | +import { isProbablyJson, isProbablyJsonRecords } from '../../util/json'; |
10 | 11 |
|
11 | 12 | // Simplify a mime type as much as we can, without throwing any errors
|
12 | 13 | export const getBaseContentType = (mimeType: string | undefined) => {
|
@@ -121,13 +122,17 @@ const mimeTypeToContentTypeMap: { [mimeType: string]: ViewableContentType } = {
|
121 | 122 | 'application/grpc-proto': 'grpc-proto',
|
122 | 123 | 'application/grpc-protobuf': 'grpc-proto',
|
123 | 124 |
|
| 125 | + // Nobody can quite agree on the names for the various sequence-of-JSON formats: |
| 126 | + 'application/jsonlines': 'json-records', |
| 127 | + 'application/json-lines': 'json-records', |
| 128 | + 'application/x-jsonlines': 'json-records', |
| 129 | + 'application/jsonl': 'json-records', |
| 130 | + 'application/x-ndjson': 'json-records', |
| 131 | + 'application/json-seq': 'json-records', |
| 132 | + |
124 | 133 | 'application/octet-stream': 'raw'
|
125 | 134 | } as const;
|
126 | 135 |
|
127 |
| -export const jsonRecordsSeparators = [ |
128 |
| - 0x1E, // SignalR record separator https://github.com/dotnet/aspnetcore/blob/v8.0.0/src/SignalR/docs/specs/HubProtocol.md#json-encoding |
129 |
| -]; |
130 |
| - |
131 | 136 | export function getContentType(mimeType: string | undefined): ViewableContentType | undefined {
|
132 | 137 | const baseContentType = getBaseContentType(mimeType);
|
133 | 138 | return mimeTypeToContentTypeMap[baseContentType!];
|
@@ -193,26 +198,18 @@ export function getCompatibleTypes(
|
193 | 198 | body = body.decodedData;
|
194 | 199 | }
|
195 | 200 |
|
196 |
| - // Examine the first char of the body, assuming it's ascii |
197 |
| - const firstChar = body && body.subarray(0, 1).toString('ascii'); |
198 |
| - |
199 | 201 | // Allow optionally formatting non-JSON-records as JSON-records, if it looks like it might be
|
200 |
| - if (body && body.length > 2 && firstChar === '{' |
201 |
| - && jsonRecordsSeparators.indexOf(body[body.length - 1]) > -1 |
202 |
| - ) { |
203 |
| - const secondToLastChar = body.subarray(body.length - 2, body.length - 1).toString('ascii'); |
204 |
| - if (secondToLastChar === '}') { |
205 |
| - types.add('json-records'); |
206 |
| - } |
| 202 | + if (!types.has('json-records') && isProbablyJsonRecords(body)) { |
| 203 | + types.add('json-records'); |
207 | 204 | }
|
208 | 205 |
|
209 |
| - // Allow optionally formatting non-JSON as JSON, if it looks like it might be |
210 |
| - if ((firstChar === '{' && !types.has('json-records')) || firstChar === '[') { |
| 206 | + if (!types.has('json-records') && isProbablyJson(body)) { |
| 207 | + // Allow optionally formatting non-JSON as JSON, if it's anything remotely close |
211 | 208 | types.add('json');
|
212 | 209 | }
|
213 | 210 |
|
214 | 211 | // Allow optionally formatting non-XML as XML, if it looks like it might be
|
215 |
| - if (firstChar === '<') { |
| 212 | + if (body?.subarray(0, 1).toString('ascii') === '<') { |
216 | 213 | types.add('xml');
|
217 | 214 | }
|
218 | 215 |
|
|
0 commit comments