Skip to content

Commit bd2429e

Browse files
author
Roman Snapko
committed
Add safe JSON parsing helper to improve error handling across services
1 parent 400667d commit bd2429e

6 files changed

Lines changed: 50 additions & 21 deletions

File tree

packages/engine/src/lib/handler/context/engine-constants.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
TestRunLimitSettings,
1515
TriggerHookType,
1616
} from '@openops/shared';
17+
import { safeResponseJson } from '../../helper/response-helper';
1718
import {
1819
createPropsResolver,
1920
PropsResolver,
@@ -232,7 +233,7 @@ export class EngineConstants {
232233
},
233234
});
234235

235-
return (await response.json()) as Project;
236+
return safeResponseJson<Project>(response);
236237
}
237238
}
238239

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export const safeResponseJson = async <T>(response: Response): Promise<T> => {
2+
const contentType = response.headers.get('content-type');
3+
if (contentType && !contentType.includes('application/json')) {
4+
const text = await response.text();
5+
throw new Error(
6+
`Expected JSON response, but received ${contentType}. Body: ${text.slice(
7+
0,
8+
100,
9+
)}${text.length > 100 ? '...' : ''}`,
10+
);
11+
}
12+
13+
try {
14+
return await response.json();
15+
} catch (e) {
16+
const text = await response.text();
17+
throw new Error(
18+
`Failed to parse JSON response. Body: ${text.slice(0, 100)}${
19+
text.length > 100 ? '...' : ''
20+
}`,
21+
);
22+
}
23+
};

packages/engine/src/lib/services/connections.service.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
ExecutionError,
1515
FetchError,
1616
} from '../helper/execution-errors';
17+
import { safeResponseJson } from '../helper/response-helper';
1718

1819
export const createConnectionService = ({
1920
projectId,
@@ -40,16 +41,17 @@ export const createConnectionService = ({
4041
httpStatus: response.status,
4142
});
4243
}
43-
const connection: AppConnection = await response.json();
44+
const connection: AppConnection = await safeResponseJson<AppConnection>(
45+
response,
46+
);
4447
if (connection.status === AppConnectionStatus.ERROR) {
4548
throw new ConnectionExpiredError(connectionName);
4649
}
4750
return getConnectionValue(connection);
4851
} catch (e) {
49-
if (e instanceof ExecutionError) {
52+
if (e instanceof ExecutionError || e instanceof Error) {
5053
throw e;
5154
}
52-
5355
return handleFetchError({
5456
url,
5557
cause: e,

packages/engine/src/lib/services/files.service.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { FilesService, WorkflowFile } from '@openops/blocks-framework';
22
import { isNil } from '@openops/shared';
33
import fs from 'fs/promises';
4+
import { safeResponseJson } from '../helper/response-helper';
45

56
const FILE_PREFIX_URL = 'file://';
67
const MEMORY_PREFIX_URL = 'memory://';
@@ -129,7 +130,7 @@ async function writeDbFile({
129130
throw new Error('Failed to store entry ' + response.body);
130131
}
131132

132-
const result = await response.json();
133+
const result = await safeResponseJson<{ url: string }>(response);
133134
return result.url;
134135
}
135136

packages/engine/src/lib/services/storage.service.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
StorageError,
2020
StorageLimitError,
2121
} from '../helper/execution-errors';
22+
import { safeResponseJson } from '../helper/response-helper';
2223

2324
export const createStorageService = ({
2425
engineToken,
@@ -42,8 +43,11 @@ export const createStorageService = ({
4243
});
4344
}
4445

45-
return await response.json();
46+
return await safeResponseJson<StoreEntry>(response);
4647
} catch (e) {
48+
if (e instanceof ExecutionError || e instanceof Error) {
49+
throw e;
50+
}
4751
return handleFetchError({
4852
url,
4953
cause: e,
@@ -78,8 +82,11 @@ export const createStorageService = ({
7882
});
7983
}
8084

81-
return await response.json();
85+
return await safeResponseJson<StoreEntry>(response);
8286
} catch (e) {
87+
if (e instanceof ExecutionError || e instanceof Error) {
88+
throw e;
89+
}
8390
return handleFetchError({
8491
url,
8592
cause: e,
@@ -107,6 +114,9 @@ export const createStorageService = ({
107114

108115
return null;
109116
} catch (e) {
117+
if (e instanceof ExecutionError || e instanceof Error) {
118+
throw e;
119+
}
110120
return handleFetchError({
111121
url,
112122
cause: e,
@@ -136,9 +146,14 @@ export const createStorageService = ({
136146
throw new Error(`Failed to list keys: ${response.statusText}`);
137147
}
138148

139-
const result = await response.json();
149+
const result = await safeResponseJson<{
150+
entries: Array<{ key: string; value: unknown }>;
151+
}>(response);
140152
return result.entries || [];
141153
} catch (e) {
154+
if (e instanceof ExecutionError || e instanceof Error) {
155+
throw e;
156+
}
142157
return handleFetchError({
143158
url,
144159
cause: e,

packages/server/worker/src/lib/trigger/hooks/extract-trigger-payload-hooks.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,6 @@ export async function extractPayloads(
3838
handleFailureFlow(flowVersion, projectId, engineToken, true);
3939
return result.output as unknown[];
4040
} else {
41-
if ('status' in result && result.status === 'INTERNAL_ERROR') {
42-
logger.warn(
43-
{
44-
result,
45-
blockName,
46-
blockVersion,
47-
flowId: flowVersion.flowId,
48-
},
49-
'Failed to execute trigger because of internal error in the engine',
50-
);
51-
return [];
52-
}
53-
5441
logger.error(
5542
{
5643
result,

0 commit comments

Comments
 (0)