From 2a7086938becf4f6b6dec41f667955404168d00b Mon Sep 17 00:00:00 2001 From: Liau Jian Jie Date: Sat, 27 Apr 2024 19:01:25 +0800 Subject: [PATCH 1/4] Add 'binary' output port --- packages/core/src/model/nodes/HttpCallNode.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/core/src/model/nodes/HttpCallNode.ts b/packages/core/src/model/nodes/HttpCallNode.ts index 55b7cc342..1f0908884 100644 --- a/packages/core/src/model/nodes/HttpCallNode.ts +++ b/packages/core/src/model/nodes/HttpCallNode.ts @@ -104,6 +104,11 @@ export class HttpCallNodeImpl extends NodeImpl { id: 'json' as PortId, title: 'JSON', }, + { + dataType: 'binary', + id: 'binary' as PortId, + title: 'Binary', + }, { dataType: 'number', id: 'statusCode' as PortId, From 18961b207f7c49b91fe1732e7323bfff4b97c9a2 Mon Sep 17 00:00:00 2001 From: Liau Jian Jie Date: Sat, 27 Apr 2024 19:01:54 +0800 Subject: [PATCH 2/4] Pass blob into binary output port --- packages/core/src/model/nodes/HttpCallNode.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/core/src/model/nodes/HttpCallNode.ts b/packages/core/src/model/nodes/HttpCallNode.ts index 1f0908884..4d1ed7f97 100644 --- a/packages/core/src/model/nodes/HttpCallNode.ts +++ b/packages/core/src/model/nodes/HttpCallNode.ts @@ -249,15 +249,16 @@ export class HttpCallNodeImpl extends NodeImpl { }, }; - const responseBody = await response.text(); + const responseBlob = await response.blob(); + const responseText = await responseBlob.text(); output['res_body' as PortId] = { type: 'string', - value: responseBody, + value: responseText, }; if (response.headers.get('content-type')?.includes('application/json')) { - const jsonData = JSON.parse(responseBody); + const jsonData = JSON.parse(responseText); output['json' as PortId] = { type: 'object', value: jsonData, @@ -269,6 +270,11 @@ export class HttpCallNodeImpl extends NodeImpl { }; } + output['binary' as PortId] = { + type: 'binary', + value: new Uint8Array(await responseBlob.arrayBuffer()), + }; + return output; } catch (err) { const { message } = getError(err); From 0451f9937a793de9517162e9248006d0c37acdf0 Mon Sep 17 00:00:00 2001 From: Liau Jian Jie Date: Sat, 27 Apr 2024 19:35:48 +0800 Subject: [PATCH 3/4] Fix crash at for binary type --- packages/app/src/components/RenderDataValue.tsx | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/app/src/components/RenderDataValue.tsx b/packages/app/src/components/RenderDataValue.tsx index a17e30a7a..0c1db44d5 100644 --- a/packages/app/src/components/RenderDataValue.tsx +++ b/packages/app/src/components/RenderDataValue.tsx @@ -205,7 +205,14 @@ const scalarRenderers: { ); }, - binary: ({ value }) => <>Binary (length {value.value.length.toLocaleString()}), + binary: ({ value }) => { + // FIXME: Coercing `value.value` into a `Uint8Array` here because `Uint8Array` gets parsed as an + // object of shape `{ [index: number]: number }` when stringified via `JSON.stringify()`. + // Consider coercing it back to `Uint8Array` at the entrypoints of the boundaries between + // browser and node.js instead. + const coercedValue = new Uint8Array(Object.values(value.value)); + return <>Binary (length {coercedValue.length.toLocaleString()}); + }, audio: ({ value }) => { const { value: { data }, From 7f54555407e303901100b8eb79945b26f9e59731 Mon Sep 17 00:00:00 2001 From: Liau Jian Jie Date: Fri, 3 May 2024 00:04:13 +0800 Subject: [PATCH 4/4] Add option to toggle between binary and text/json outputs --- packages/core/src/model/nodes/HttpCallNode.ts | 86 +++++++++++-------- 1 file changed, 51 insertions(+), 35 deletions(-) diff --git a/packages/core/src/model/nodes/HttpCallNode.ts b/packages/core/src/model/nodes/HttpCallNode.ts index 4d1ed7f97..9fe70d87a 100644 --- a/packages/core/src/model/nodes/HttpCallNode.ts +++ b/packages/core/src/model/nodes/HttpCallNode.ts @@ -28,6 +28,8 @@ export type HttpCallNodeData = { body: string; useBodyInput?: boolean; + isBinaryOutput?: boolean; + errorOnNon200?: boolean; }; @@ -93,22 +95,29 @@ export class HttpCallNodeImpl extends NodeImpl { } getOutputDefinitions(): NodeOutputDefinition[] { - return [ - { - dataType: 'string', - id: 'res_body' as PortId, - title: 'Body', - }, - { - dataType: 'object', - id: 'json' as PortId, - title: 'JSON', - }, - { + const outputDefinitions: NodeOutputDefinition[] = []; + if (this.data.isBinaryOutput) { + outputDefinitions.push({ dataType: 'binary', id: 'binary' as PortId, title: 'Binary', - }, + }); + } else { + outputDefinitions.push( + { + dataType: 'string', + id: 'res_body' as PortId, + title: 'Body', + }, + { + dataType: 'object', + id: 'json' as PortId, + title: 'JSON', + }, + ); + } + + outputDefinitions.push( { dataType: 'number', id: 'statusCode' as PortId, @@ -119,7 +128,9 @@ export class HttpCallNodeImpl extends NodeImpl { id: 'res_headers' as PortId, title: 'Headers', }, - ]; + ); + + return outputDefinitions; } getEditors(): EditorDefinition[] { @@ -156,6 +167,11 @@ export class HttpCallNodeImpl extends NodeImpl { useInputToggleDataKey: 'useBodyInput', language: 'json', }, + { + type: 'toggle', + label: 'Whether response body is expected to be a binary', + dataKey: 'isBinaryOutput', + }, { type: 'toggle', label: 'Error on non-200 status code', @@ -249,32 +265,32 @@ export class HttpCallNodeImpl extends NodeImpl { }, }; - const responseBlob = await response.blob(); - const responseText = await responseBlob.text(); - - output['res_body' as PortId] = { - type: 'string', - value: responseText, - }; - - if (response.headers.get('content-type')?.includes('application/json')) { - const jsonData = JSON.parse(responseText); - output['json' as PortId] = { - type: 'object', - value: jsonData, + if (this.data.isBinaryOutput) { + const responseBlob = await response.blob(); + output['binary' as PortId] = { + type: 'binary', + value: new Uint8Array(await responseBlob.arrayBuffer()), }; } else { - output['json' as PortId] = { - type: 'control-flow-excluded', - value: undefined, + const responseText = await response.text(); + output['res_body' as PortId] = { + type: 'string', + value: responseText, }; + if (response.headers.get('content-type')?.includes('application/json')) { + const jsonData = JSON.parse(responseText); + output['json' as PortId] = { + type: 'object', + value: jsonData, + }; + } else { + output['json' as PortId] = { + type: 'control-flow-excluded', + value: undefined, + }; + } } - output['binary' as PortId] = { - type: 'binary', - value: new Uint8Array(await responseBlob.arrayBuffer()), - }; - return output; } catch (err) { const { message } = getError(err);