@codemation/core-nodes 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/index.cjs +76 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +80 -0
- package/dist/index.d.ts +80 -0
- package/dist/index.js +76 -16
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/http/HttpBodyBuilder.ts +45 -17
- package/src/http/HttpRequestExecutor.ts +4 -1
- package/src/http/httpRequest.types.ts +27 -0
- package/src/nodes/HttpRequestNodeFactory.ts +69 -1
- package/src/nodes/httpRequest.ts +44 -0
package/dist/index.d.cts
CHANGED
|
@@ -1398,6 +1398,15 @@ type HttpBodySpec = Readonly<{
|
|
|
1398
1398
|
kind: "multipart";
|
|
1399
1399
|
fields: Readonly<Record<string, string>>;
|
|
1400
1400
|
binaries?: Readonly<Record<string, BinaryRef>>;
|
|
1401
|
+
}> | Readonly<{
|
|
1402
|
+
/**
|
|
1403
|
+
* Send raw bytes from a binary slot as the request body.
|
|
1404
|
+
* The binary attachment's `mimeType` is used as `Content-Type` unless
|
|
1405
|
+
* the request `headers` map already contains `content-type`.
|
|
1406
|
+
*/
|
|
1407
|
+
kind: "binary";
|
|
1408
|
+
/** Key into `item.binary` to read the request body bytes from. */
|
|
1409
|
+
slot: string;
|
|
1401
1410
|
}>;
|
|
1402
1411
|
/**
|
|
1403
1412
|
* Session interface that credential types implement.
|
|
@@ -1429,6 +1438,15 @@ type HttpRequestSpec = Readonly<{
|
|
|
1429
1438
|
mode: "auto" | "always" | "never";
|
|
1430
1439
|
binaryName: string;
|
|
1431
1440
|
}>;
|
|
1441
|
+
/**
|
|
1442
|
+
* When set to `"binary"`, the response body is written to a binary slot
|
|
1443
|
+
* instead of being parsed as JSON/text. Overrides `download` mode.
|
|
1444
|
+
*/
|
|
1445
|
+
responseFormat?: "json" | "text" | "binary";
|
|
1446
|
+
/** Binary slot name for the response body when `responseFormat === "binary"`. Defaults to `"response"`. */
|
|
1447
|
+
responseBinarySlot?: string;
|
|
1448
|
+
/** Maximum allowed response size in bytes (checked against Content-Length before allocating). Defaults to 100 MiB. */
|
|
1449
|
+
responseSizeCapBytes?: number;
|
|
1432
1450
|
/** Execution context — needed for binary attach. */
|
|
1433
1451
|
ctx: NodeExecutionContext<RunnableNodeConfig<unknown, unknown>>;
|
|
1434
1452
|
}>;
|
|
@@ -1446,6 +1464,14 @@ type HttpRequestResult = Readonly<{
|
|
|
1446
1464
|
json?: unknown;
|
|
1447
1465
|
text?: string;
|
|
1448
1466
|
bodyBinaryName?: string;
|
|
1467
|
+
/** Set when `responseFormat === "binary"`. Name of the binary slot the response body was written to. */
|
|
1468
|
+
binarySlot?: string;
|
|
1469
|
+
/** Set when `responseFormat === "binary"`. The MIME type of the stored response. */
|
|
1470
|
+
contentType?: string;
|
|
1471
|
+
/** Set when `responseFormat === "binary"`. Size in bytes of the stored response. */
|
|
1472
|
+
size?: number;
|
|
1473
|
+
/** Set when `responseFormat === "binary"`. Filename inferred from URL or Content-Disposition. */
|
|
1474
|
+
filename?: string;
|
|
1449
1475
|
}>;
|
|
1450
1476
|
//#endregion
|
|
1451
1477
|
//#region src/credentials/ApiKeyCredentialType.d.ts
|
|
@@ -2300,6 +2326,7 @@ declare class HttpRequestNode implements RunnableNode<HttpRequest<any, any>> {
|
|
|
2300
2326
|
readonly outputPorts: readonly ["main"];
|
|
2301
2327
|
execute(args: RunnableNodeExecuteArgs<HttpRequest<any, any>>): Promise<unknown>;
|
|
2302
2328
|
private executeItem;
|
|
2329
|
+
private handleBinaryResponse;
|
|
2303
2330
|
private resolveCredential;
|
|
2304
2331
|
private resolveUrl;
|
|
2305
2332
|
private asRecord;
|
|
@@ -2325,6 +2352,14 @@ type HttpRequestOutputJson = Readonly<{
|
|
|
2325
2352
|
json?: unknown;
|
|
2326
2353
|
text?: string;
|
|
2327
2354
|
bodyBinaryName?: string;
|
|
2355
|
+
/** Set when `responseFormat === "binary"`. Name of the binary slot the response was stored in. */
|
|
2356
|
+
binarySlot?: string;
|
|
2357
|
+
/** Set when `responseFormat === "binary"`. MIME type of the stored response. */
|
|
2358
|
+
contentType?: string;
|
|
2359
|
+
/** Set when `responseFormat === "binary"`. Size in bytes of the stored response. */
|
|
2360
|
+
size?: number;
|
|
2361
|
+
/** Set when `responseFormat === "binary"`. Filename inferred from URL or Content-Disposition. */
|
|
2362
|
+
filename?: string;
|
|
2328
2363
|
}>;
|
|
2329
2364
|
/**
|
|
2330
2365
|
* The built-in HTTP request credential type IDs accepted by the `HttpRequest` node.
|
|
@@ -2359,6 +2394,27 @@ declare class HttpRequest<TInputJson$1 = Readonly<{
|
|
|
2359
2394
|
credentialSlot?: string;
|
|
2360
2395
|
binaryName?: string;
|
|
2361
2396
|
downloadMode?: HttpRequestDownloadMode;
|
|
2397
|
+
/**
|
|
2398
|
+
* Controls how the response body is handled.
|
|
2399
|
+
* - `"json"` / `"text"`: existing behaviour (parse + emit on `item.json`).
|
|
2400
|
+
* - `"binary"`: read the response as raw bytes and store via `ctx.binary.attach`.
|
|
2401
|
+
* The output JSON contains `{ status, headers, binarySlot, contentType, size, filename }`
|
|
2402
|
+
* but NOT the raw bytes. Use `responseBinarySlot` to name the slot (default `"response"`).
|
|
2403
|
+
*
|
|
2404
|
+
* When omitted, the existing `downloadMode` logic applies (backward-compatible).
|
|
2405
|
+
*/
|
|
2406
|
+
responseFormat?: "json" | "text" | "binary";
|
|
2407
|
+
/**
|
|
2408
|
+
* Name of the binary slot to write the response body into when `responseFormat === "binary"`.
|
|
2409
|
+
* Defaults to `"response"`.
|
|
2410
|
+
*/
|
|
2411
|
+
responseBinarySlot?: string;
|
|
2412
|
+
/**
|
|
2413
|
+
* Maximum response size in bytes for binary mode. Checked against the `Content-Length`
|
|
2414
|
+
* response header before allocating memory. Defaults to 100 MiB (104857600).
|
|
2415
|
+
* Requests whose `Content-Length` exceeds this cap are rejected before the body is read.
|
|
2416
|
+
*/
|
|
2417
|
+
responseSizeCapBytes?: number;
|
|
2362
2418
|
id?: string;
|
|
2363
2419
|
}>;
|
|
2364
2420
|
readonly retryPolicy: RetryPolicySpec;
|
|
@@ -2392,6 +2448,27 @@ declare class HttpRequest<TInputJson$1 = Readonly<{
|
|
|
2392
2448
|
credentialSlot?: string;
|
|
2393
2449
|
binaryName?: string;
|
|
2394
2450
|
downloadMode?: HttpRequestDownloadMode;
|
|
2451
|
+
/**
|
|
2452
|
+
* Controls how the response body is handled.
|
|
2453
|
+
* - `"json"` / `"text"`: existing behaviour (parse + emit on `item.json`).
|
|
2454
|
+
* - `"binary"`: read the response as raw bytes and store via `ctx.binary.attach`.
|
|
2455
|
+
* The output JSON contains `{ status, headers, binarySlot, contentType, size, filename }`
|
|
2456
|
+
* but NOT the raw bytes. Use `responseBinarySlot` to name the slot (default `"response"`).
|
|
2457
|
+
*
|
|
2458
|
+
* When omitted, the existing `downloadMode` logic applies (backward-compatible).
|
|
2459
|
+
*/
|
|
2460
|
+
responseFormat?: "json" | "text" | "binary";
|
|
2461
|
+
/**
|
|
2462
|
+
* Name of the binary slot to write the response body into when `responseFormat === "binary"`.
|
|
2463
|
+
* Defaults to `"response"`.
|
|
2464
|
+
*/
|
|
2465
|
+
responseBinarySlot?: string;
|
|
2466
|
+
/**
|
|
2467
|
+
* Maximum response size in bytes for binary mode. Checked against the `Content-Length`
|
|
2468
|
+
* response header before allocating memory. Defaults to 100 MiB (104857600).
|
|
2469
|
+
* Requests whose `Content-Length` exceeds this cap are rejected before the body is read.
|
|
2470
|
+
*/
|
|
2471
|
+
responseSizeCapBytes?: number;
|
|
2395
2472
|
id?: string;
|
|
2396
2473
|
}>, retryPolicy?: RetryPolicySpec);
|
|
2397
2474
|
get id(): string | undefined;
|
|
@@ -2399,6 +2476,9 @@ declare class HttpRequest<TInputJson$1 = Readonly<{
|
|
|
2399
2476
|
get urlField(): string;
|
|
2400
2477
|
get binaryName(): string;
|
|
2401
2478
|
get downloadMode(): HttpRequestDownloadMode;
|
|
2479
|
+
get responseFormat(): "json" | "text" | "binary" | undefined;
|
|
2480
|
+
get responseBinarySlot(): string;
|
|
2481
|
+
get responseSizeCapBytes(): number;
|
|
2402
2482
|
getCredentialRequirements(): ReadonlyArray<CredentialRequirement>;
|
|
2403
2483
|
}
|
|
2404
2484
|
//#endregion
|
package/dist/index.d.ts
CHANGED
|
@@ -1398,6 +1398,15 @@ type HttpBodySpec = Readonly<{
|
|
|
1398
1398
|
kind: "multipart";
|
|
1399
1399
|
fields: Readonly<Record<string, string>>;
|
|
1400
1400
|
binaries?: Readonly<Record<string, BinaryRef>>;
|
|
1401
|
+
}> | Readonly<{
|
|
1402
|
+
/**
|
|
1403
|
+
* Send raw bytes from a binary slot as the request body.
|
|
1404
|
+
* The binary attachment's `mimeType` is used as `Content-Type` unless
|
|
1405
|
+
* the request `headers` map already contains `content-type`.
|
|
1406
|
+
*/
|
|
1407
|
+
kind: "binary";
|
|
1408
|
+
/** Key into `item.binary` to read the request body bytes from. */
|
|
1409
|
+
slot: string;
|
|
1401
1410
|
}>;
|
|
1402
1411
|
/**
|
|
1403
1412
|
* Session interface that credential types implement.
|
|
@@ -1429,6 +1438,15 @@ type HttpRequestSpec = Readonly<{
|
|
|
1429
1438
|
mode: "auto" | "always" | "never";
|
|
1430
1439
|
binaryName: string;
|
|
1431
1440
|
}>;
|
|
1441
|
+
/**
|
|
1442
|
+
* When set to `"binary"`, the response body is written to a binary slot
|
|
1443
|
+
* instead of being parsed as JSON/text. Overrides `download` mode.
|
|
1444
|
+
*/
|
|
1445
|
+
responseFormat?: "json" | "text" | "binary";
|
|
1446
|
+
/** Binary slot name for the response body when `responseFormat === "binary"`. Defaults to `"response"`. */
|
|
1447
|
+
responseBinarySlot?: string;
|
|
1448
|
+
/** Maximum allowed response size in bytes (checked against Content-Length before allocating). Defaults to 100 MiB. */
|
|
1449
|
+
responseSizeCapBytes?: number;
|
|
1432
1450
|
/** Execution context — needed for binary attach. */
|
|
1433
1451
|
ctx: NodeExecutionContext<RunnableNodeConfig<unknown, unknown>>;
|
|
1434
1452
|
}>;
|
|
@@ -1446,6 +1464,14 @@ type HttpRequestResult = Readonly<{
|
|
|
1446
1464
|
json?: unknown;
|
|
1447
1465
|
text?: string;
|
|
1448
1466
|
bodyBinaryName?: string;
|
|
1467
|
+
/** Set when `responseFormat === "binary"`. Name of the binary slot the response body was written to. */
|
|
1468
|
+
binarySlot?: string;
|
|
1469
|
+
/** Set when `responseFormat === "binary"`. The MIME type of the stored response. */
|
|
1470
|
+
contentType?: string;
|
|
1471
|
+
/** Set when `responseFormat === "binary"`. Size in bytes of the stored response. */
|
|
1472
|
+
size?: number;
|
|
1473
|
+
/** Set when `responseFormat === "binary"`. Filename inferred from URL or Content-Disposition. */
|
|
1474
|
+
filename?: string;
|
|
1449
1475
|
}>;
|
|
1450
1476
|
//#endregion
|
|
1451
1477
|
//#region src/credentials/ApiKeyCredentialType.d.ts
|
|
@@ -2300,6 +2326,7 @@ declare class HttpRequestNode implements RunnableNode<HttpRequest<any, any>> {
|
|
|
2300
2326
|
readonly outputPorts: readonly ["main"];
|
|
2301
2327
|
execute(args: RunnableNodeExecuteArgs<HttpRequest<any, any>>): Promise<unknown>;
|
|
2302
2328
|
private executeItem;
|
|
2329
|
+
private handleBinaryResponse;
|
|
2303
2330
|
private resolveCredential;
|
|
2304
2331
|
private resolveUrl;
|
|
2305
2332
|
private asRecord;
|
|
@@ -2325,6 +2352,14 @@ type HttpRequestOutputJson = Readonly<{
|
|
|
2325
2352
|
json?: unknown;
|
|
2326
2353
|
text?: string;
|
|
2327
2354
|
bodyBinaryName?: string;
|
|
2355
|
+
/** Set when `responseFormat === "binary"`. Name of the binary slot the response was stored in. */
|
|
2356
|
+
binarySlot?: string;
|
|
2357
|
+
/** Set when `responseFormat === "binary"`. MIME type of the stored response. */
|
|
2358
|
+
contentType?: string;
|
|
2359
|
+
/** Set when `responseFormat === "binary"`. Size in bytes of the stored response. */
|
|
2360
|
+
size?: number;
|
|
2361
|
+
/** Set when `responseFormat === "binary"`. Filename inferred from URL or Content-Disposition. */
|
|
2362
|
+
filename?: string;
|
|
2328
2363
|
}>;
|
|
2329
2364
|
/**
|
|
2330
2365
|
* The built-in HTTP request credential type IDs accepted by the `HttpRequest` node.
|
|
@@ -2359,6 +2394,27 @@ declare class HttpRequest<TInputJson$1 = Readonly<{
|
|
|
2359
2394
|
credentialSlot?: string;
|
|
2360
2395
|
binaryName?: string;
|
|
2361
2396
|
downloadMode?: HttpRequestDownloadMode;
|
|
2397
|
+
/**
|
|
2398
|
+
* Controls how the response body is handled.
|
|
2399
|
+
* - `"json"` / `"text"`: existing behaviour (parse + emit on `item.json`).
|
|
2400
|
+
* - `"binary"`: read the response as raw bytes and store via `ctx.binary.attach`.
|
|
2401
|
+
* The output JSON contains `{ status, headers, binarySlot, contentType, size, filename }`
|
|
2402
|
+
* but NOT the raw bytes. Use `responseBinarySlot` to name the slot (default `"response"`).
|
|
2403
|
+
*
|
|
2404
|
+
* When omitted, the existing `downloadMode` logic applies (backward-compatible).
|
|
2405
|
+
*/
|
|
2406
|
+
responseFormat?: "json" | "text" | "binary";
|
|
2407
|
+
/**
|
|
2408
|
+
* Name of the binary slot to write the response body into when `responseFormat === "binary"`.
|
|
2409
|
+
* Defaults to `"response"`.
|
|
2410
|
+
*/
|
|
2411
|
+
responseBinarySlot?: string;
|
|
2412
|
+
/**
|
|
2413
|
+
* Maximum response size in bytes for binary mode. Checked against the `Content-Length`
|
|
2414
|
+
* response header before allocating memory. Defaults to 100 MiB (104857600).
|
|
2415
|
+
* Requests whose `Content-Length` exceeds this cap are rejected before the body is read.
|
|
2416
|
+
*/
|
|
2417
|
+
responseSizeCapBytes?: number;
|
|
2362
2418
|
id?: string;
|
|
2363
2419
|
}>;
|
|
2364
2420
|
readonly retryPolicy: RetryPolicySpec;
|
|
@@ -2392,6 +2448,27 @@ declare class HttpRequest<TInputJson$1 = Readonly<{
|
|
|
2392
2448
|
credentialSlot?: string;
|
|
2393
2449
|
binaryName?: string;
|
|
2394
2450
|
downloadMode?: HttpRequestDownloadMode;
|
|
2451
|
+
/**
|
|
2452
|
+
* Controls how the response body is handled.
|
|
2453
|
+
* - `"json"` / `"text"`: existing behaviour (parse + emit on `item.json`).
|
|
2454
|
+
* - `"binary"`: read the response as raw bytes and store via `ctx.binary.attach`.
|
|
2455
|
+
* The output JSON contains `{ status, headers, binarySlot, contentType, size, filename }`
|
|
2456
|
+
* but NOT the raw bytes. Use `responseBinarySlot` to name the slot (default `"response"`).
|
|
2457
|
+
*
|
|
2458
|
+
* When omitted, the existing `downloadMode` logic applies (backward-compatible).
|
|
2459
|
+
*/
|
|
2460
|
+
responseFormat?: "json" | "text" | "binary";
|
|
2461
|
+
/**
|
|
2462
|
+
* Name of the binary slot to write the response body into when `responseFormat === "binary"`.
|
|
2463
|
+
* Defaults to `"response"`.
|
|
2464
|
+
*/
|
|
2465
|
+
responseBinarySlot?: string;
|
|
2466
|
+
/**
|
|
2467
|
+
* Maximum response size in bytes for binary mode. Checked against the `Content-Length`
|
|
2468
|
+
* response header before allocating memory. Defaults to 100 MiB (104857600).
|
|
2469
|
+
* Requests whose `Content-Length` exceeds this cap are rejected before the body is read.
|
|
2470
|
+
*/
|
|
2471
|
+
responseSizeCapBytes?: number;
|
|
2395
2472
|
id?: string;
|
|
2396
2473
|
}>, retryPolicy?: RetryPolicySpec);
|
|
2397
2474
|
get id(): string | undefined;
|
|
@@ -2399,6 +2476,9 @@ declare class HttpRequest<TInputJson$1 = Readonly<{
|
|
|
2399
2476
|
get urlField(): string;
|
|
2400
2477
|
get binaryName(): string;
|
|
2401
2478
|
get downloadMode(): HttpRequestDownloadMode;
|
|
2479
|
+
get responseFormat(): "json" | "text" | "binary" | undefined;
|
|
2480
|
+
get responseBinarySlot(): string;
|
|
2481
|
+
get responseSizeCapBytes(): number;
|
|
2402
2482
|
getCredentialRequirements(): ReadonlyArray<CredentialRequirement>;
|
|
2403
2483
|
}
|
|
2404
2484
|
//#endregion
|
package/dist/index.js
CHANGED
|
@@ -295,7 +295,8 @@ var HttpRequestExecutor = class {
|
|
|
295
295
|
...credentialDelta.query ?? {}
|
|
296
296
|
};
|
|
297
297
|
const encodedBody = await this.bodyBuilder.build(spec.body, item, spec.ctx);
|
|
298
|
-
|
|
298
|
+
const hasExplicitContentType = Object.keys(mergedHeaders).some((k) => k.toLowerCase() === "content-type");
|
|
299
|
+
if (encodedBody && encodedBody.contentType && !hasExplicitContentType) mergedHeaders["content-type"] = encodedBody.contentType;
|
|
299
300
|
return {
|
|
300
301
|
url: this.urlBuilder.build(spec.url, mergedQuery),
|
|
301
302
|
init: {
|
|
@@ -394,21 +395,7 @@ var HttpBodyBuilder = class {
|
|
|
394
395
|
if (attachment) {
|
|
395
396
|
const readResult = await ctx.binary.openReadStream(attachment);
|
|
396
397
|
if (readResult) {
|
|
397
|
-
const
|
|
398
|
-
const chunks = [];
|
|
399
|
-
let done = false;
|
|
400
|
-
while (!done) {
|
|
401
|
-
const result = await reader.read();
|
|
402
|
-
done = result.done;
|
|
403
|
-
if (result.value) chunks.push(result.value);
|
|
404
|
-
}
|
|
405
|
-
const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
|
|
406
|
-
const merged = new Uint8Array(totalLength);
|
|
407
|
-
let offset = 0;
|
|
408
|
-
for (const chunk of chunks) {
|
|
409
|
-
merged.set(chunk, offset);
|
|
410
|
-
offset += chunk.length;
|
|
411
|
-
}
|
|
398
|
+
const merged = await this.readStreamToBuffer(readResult.body);
|
|
412
399
|
const blob = new Blob([merged], { type: attachment.mimeType });
|
|
413
400
|
formData.append(fieldName, blob, attachment.filename ?? binaryRef);
|
|
414
401
|
}
|
|
@@ -419,6 +406,34 @@ var HttpBodyBuilder = class {
|
|
|
419
406
|
contentType: ""
|
|
420
407
|
};
|
|
421
408
|
}
|
|
409
|
+
if (spec.kind === "binary") {
|
|
410
|
+
const attachment = item.binary?.[spec.slot];
|
|
411
|
+
if (!attachment) throw new Error(`HttpRequest bodyFormat "binary": no binary attachment found at slot "${spec.slot}". Ensure a previous node attached binary data at that slot.`);
|
|
412
|
+
const readResult = await ctx.binary.openReadStream(attachment);
|
|
413
|
+
if (!readResult) throw new Error(`HttpRequest bodyFormat "binary": could not open read stream for slot "${spec.slot}".`);
|
|
414
|
+
return {
|
|
415
|
+
body: readResult.body,
|
|
416
|
+
contentType: attachment.mimeType
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
async readStreamToBuffer(stream) {
|
|
421
|
+
const reader = stream.getReader();
|
|
422
|
+
const chunks = [];
|
|
423
|
+
let done = false;
|
|
424
|
+
while (!done) {
|
|
425
|
+
const result = await reader.read();
|
|
426
|
+
done = result.done;
|
|
427
|
+
if (result.value) chunks.push(result.value);
|
|
428
|
+
}
|
|
429
|
+
const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
|
|
430
|
+
const merged = new Uint8Array(new ArrayBuffer(totalLength));
|
|
431
|
+
let offset = 0;
|
|
432
|
+
for (const chunk of chunks) {
|
|
433
|
+
merged.set(chunk, offset);
|
|
434
|
+
offset += chunk.length;
|
|
435
|
+
}
|
|
436
|
+
return merged;
|
|
422
437
|
}
|
|
423
438
|
};
|
|
424
439
|
|
|
@@ -6512,12 +6527,16 @@ let HttpRequestNode = class HttpRequestNode$1 {
|
|
|
6512
6527
|
mode: ctx.config.downloadMode,
|
|
6513
6528
|
binaryName: ctx.config.binaryName
|
|
6514
6529
|
},
|
|
6530
|
+
responseFormat: ctx.config.responseFormat,
|
|
6531
|
+
responseBinarySlot: ctx.config.responseBinarySlot,
|
|
6532
|
+
responseSizeCapBytes: ctx.config.responseSizeCapBytes,
|
|
6515
6533
|
ctx
|
|
6516
6534
|
};
|
|
6517
6535
|
const { url: resolvedUrl, init } = await new HttpRequestExecutor(globalThis.fetch, new HttpBodyBuilder(), new HttpUrlBuilder()).buildRequest(spec, item);
|
|
6518
6536
|
const response = await globalThis.fetch(resolvedUrl, init);
|
|
6519
6537
|
const headers = this.readHeaders(response.headers);
|
|
6520
6538
|
const mimeType = this.resolveMimeType(headers);
|
|
6539
|
+
if (ctx.config.responseFormat === "binary") return await this.handleBinaryResponse(response, resolvedUrl, headers, mimeType, ctx);
|
|
6521
6540
|
const binaryName = ctx.config.binaryName;
|
|
6522
6541
|
if (this.shouldAttachBody(ctx.config.downloadMode, mimeType)) {
|
|
6523
6542
|
const outputJson = {
|
|
@@ -6561,6 +6580,36 @@ let HttpRequestNode = class HttpRequestNode$1 {
|
|
|
6561
6580
|
...text !== void 0 ? { text } : {}
|
|
6562
6581
|
} };
|
|
6563
6582
|
}
|
|
6583
|
+
async handleBinaryResponse(response, resolvedUrl, headers, mimeType, ctx) {
|
|
6584
|
+
const slotName = ctx.config.responseBinarySlot;
|
|
6585
|
+
const sizeCap = ctx.config.responseSizeCapBytes;
|
|
6586
|
+
const contentLengthHeader = headers["content-length"];
|
|
6587
|
+
if (contentLengthHeader) {
|
|
6588
|
+
const declaredSize = parseInt(contentLengthHeader, 10);
|
|
6589
|
+
if (!isNaN(declaredSize) && declaredSize > sizeCap) throw new Error(`HttpRequest responseFormat "binary": response Content-Length (${declaredSize} bytes) exceeds responseSizeCapBytes (${sizeCap} bytes).`);
|
|
6590
|
+
}
|
|
6591
|
+
const filename = this.resolveFilename(resolvedUrl, headers);
|
|
6592
|
+
const attachment = await ctx.binary.attach({
|
|
6593
|
+
name: slotName,
|
|
6594
|
+
body: response.body ? response.body : new Uint8Array(await response.arrayBuffer()),
|
|
6595
|
+
mimeType,
|
|
6596
|
+
filename
|
|
6597
|
+
});
|
|
6598
|
+
let outputItem = { json: {
|
|
6599
|
+
url: resolvedUrl,
|
|
6600
|
+
method: ctx.config.method,
|
|
6601
|
+
ok: response.ok,
|
|
6602
|
+
status: response.status,
|
|
6603
|
+
statusText: response.statusText,
|
|
6604
|
+
headers,
|
|
6605
|
+
binarySlot: slotName,
|
|
6606
|
+
contentType: mimeType,
|
|
6607
|
+
size: attachment.size,
|
|
6608
|
+
...filename !== void 0 ? { filename } : {}
|
|
6609
|
+
} };
|
|
6610
|
+
outputItem = ctx.binary.withAttachment(outputItem, slotName, attachment);
|
|
6611
|
+
return outputItem;
|
|
6612
|
+
}
|
|
6564
6613
|
async resolveCredential(ctx) {
|
|
6565
6614
|
const slotKey = ctx.config.args.credentialSlot;
|
|
6566
6615
|
if (!slotKey) return;
|
|
@@ -6632,6 +6681,8 @@ const HTTP_REQUEST_ACCEPTED_CREDENTIAL_TYPES = [
|
|
|
6632
6681
|
basicAuthCredentialType.definition.typeId,
|
|
6633
6682
|
oauth2ClientCredentialsType.definition.typeId
|
|
6634
6683
|
];
|
|
6684
|
+
/** Default maximum response size for binary mode: 100 MiB. */
|
|
6685
|
+
const DEFAULT_RESPONSE_SIZE_CAP_BYTES = 100 * 1024 * 1024;
|
|
6635
6686
|
var HttpRequest = class {
|
|
6636
6687
|
kind = "node";
|
|
6637
6688
|
type = HttpRequestNode;
|
|
@@ -6657,6 +6708,15 @@ var HttpRequest = class {
|
|
|
6657
6708
|
get downloadMode() {
|
|
6658
6709
|
return this.args.downloadMode ?? "auto";
|
|
6659
6710
|
}
|
|
6711
|
+
get responseFormat() {
|
|
6712
|
+
return this.args.responseFormat;
|
|
6713
|
+
}
|
|
6714
|
+
get responseBinarySlot() {
|
|
6715
|
+
return this.args.responseBinarySlot ?? "response";
|
|
6716
|
+
}
|
|
6717
|
+
get responseSizeCapBytes() {
|
|
6718
|
+
return this.args.responseSizeCapBytes ?? DEFAULT_RESPONSE_SIZE_CAP_BYTES;
|
|
6719
|
+
}
|
|
6660
6720
|
getCredentialRequirements() {
|
|
6661
6721
|
if (!this.args.credentialSlot) return [];
|
|
6662
6722
|
return [{
|