@things-factory/integration-base 9.0.33 → 9.0.34
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/dist-server/engine/connector/headless-connector.d.ts +1 -0
- package/dist-server/engine/connector/headless-connector.js +117 -61
- package/dist-server/engine/connector/headless-connector.js.map +1 -1
- package/dist-server/engine/resource-pool/headless-pool.d.ts +29 -1
- package/dist-server/engine/resource-pool/headless-pool.js +70 -53
- package/dist-server/engine/resource-pool/headless-pool.js.map +1 -1
- package/dist-server/engine/task/headless-delete.js +9 -61
- package/dist-server/engine/task/headless-delete.js.map +1 -1
- package/dist-server/engine/task/headless-get.js +9 -55
- package/dist-server/engine/task/headless-get.js.map +1 -1
- package/dist-server/engine/task/headless-patch.js +11 -74
- package/dist-server/engine/task/headless-patch.js.map +1 -1
- package/dist-server/engine/task/headless-post.js +11 -74
- package/dist-server/engine/task/headless-post.js.map +1 -1
- package/dist-server/engine/task/headless-put.js +11 -74
- package/dist-server/engine/task/headless-put.js.map +1 -1
- package/dist-server/engine/task/utils/headless-request-with-recovery.d.ts +18 -0
- package/dist-server/engine/task/utils/headless-request-with-recovery.js +221 -0
- package/dist-server/engine/task/utils/headless-request-with-recovery.js.map +1 -0
- package/dist-server/restful/unstable/headless-pool-status.d.ts +1 -0
- package/dist-server/restful/unstable/headless-pool-status.js +78 -0
- package/dist-server/restful/unstable/headless-pool-status.js.map +1 -0
- package/dist-server/restful/unstable/index.d.ts +1 -0
- package/dist-server/restful/unstable/index.js +1 -0
- package/dist-server/restful/unstable/index.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -9
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"headless-delete.js","sourceRoot":"","sources":["../../../server/engine/task/headless-delete.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"headless-delete.js","sourceRoot":"","sources":["../../../server/engine/task/headless-delete.ts"],"names":[],"mappings":";;AAAA,oDAA+C;AAC/C,2FAA2F;AAE3F,KAAK,UAAU,cAAc,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;IAC1D,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAA;IAChE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,WAAW,IAAI,EAAE,CAAA;IAExE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAA,mEAAkC,EACrD,cAAc,EACd;YACE,MAAM,EAAE,QAAQ;YAChB,IAAI;YACJ,OAAO,EAAE,cAAc;YACvB,WAAW;YACX,UAAU,EAAE,CAAC;SACd,EACD,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CACzB,CAAA;QAED,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;SAClB,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAA;QAC/C,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC;AAED,cAAc,CAAC,aAAa,GAAG;IAC7B;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,MAAM;KACd;IACD;QACE,IAAI,EAAE,cAAc;QACpB,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;KACjB;IACD;QACE,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,kBAAkB;KAC1B;CACF,CAAA;AAED,4BAAY,CAAC,mBAAmB,CAAC,iBAAiB,EAAE,cAAc,CAAC,CAAA","sourcesContent":["import { TaskRegistry } from '../task-registry'\nimport { executeHeadlessRequestWithRecovery } from './utils/headless-request-with-recovery'\n\nasync function HeadlessDelete(step, { logger, data, domain }) {\n const { connection: connectionName, params: stepOptions } = step\n const { headers: requestHeaders, path, queryParams } = stepOptions || {}\n\n try {\n const result = await executeHeadlessRequestWithRecovery(\n connectionName,\n {\n method: 'DELETE',\n path,\n headers: requestHeaders,\n queryParams,\n maxRetries: 2\n },\n { logger, data, domain }\n )\n\n return {\n data: result.data\n }\n } catch (error) {\n logger.error('Error in HeadlessDelete:', error)\n throw error\n }\n}\n\nHeadlessDelete.parameterSpec = [\n {\n type: 'string',\n name: 'path',\n label: 'path'\n },\n {\n type: 'http-headers',\n name: 'headers',\n label: 'headers'\n },\n {\n type: 'options',\n name: 'queryParams',\n label: 'query-parameters'\n }\n]\n\nTaskRegistry.registerTaskHandler('headless-delete', HeadlessDelete)"]}
|
@@ -1,72 +1,26 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
const url_1 = require("url");
|
4
3
|
const task_registry_1 = require("../task-registry");
|
5
|
-
const
|
4
|
+
const headless_request_with_recovery_1 = require("./utils/headless-request-with-recovery");
|
6
5
|
async function HeadlessGet(step, { logger, data, domain }) {
|
7
6
|
const { connection: connectionName, params: stepOptions } = step;
|
8
7
|
const { headers: requestHeaders, path, queryParams } = stepOptions || {};
|
9
|
-
const connection = await connection_manager_1.ConnectionManager.getConnectionInstanceByName(domain, connectionName);
|
10
|
-
if (!connection) {
|
11
|
-
throw new Error(`Connection '${connectionName}' is not established.`);
|
12
|
-
}
|
13
|
-
const { endpoint, params: connectionParams, acquireSessionPage, releasePage } = connection;
|
14
|
-
const headers = {
|
15
|
-
...requestHeaders
|
16
|
-
};
|
17
|
-
const page = await acquireSessionPage();
|
18
8
|
try {
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
let requestUrl = new url_1.URL(path, endpoint);
|
27
|
-
if (queryParams && typeof queryParams === 'object') {
|
28
|
-
Object.keys(queryParams).forEach(key => {
|
29
|
-
if (queryParams[key] !== null && queryParams[key] !== undefined) {
|
30
|
-
requestUrl.searchParams.append(key, String(queryParams[key]));
|
31
|
-
}
|
32
|
-
});
|
33
|
-
}
|
34
|
-
// headless-scrap과 동일한 방식으로 페이지 이동하여 세션 유지
|
35
|
-
await page.goto(requestUrl, { waitUntil: 'networkidle2' });
|
36
|
-
// 페이지 내에서 GET 요청 실행 (세션 유지)
|
37
|
-
const response = await page.evaluate(async (urlString, headers) => {
|
38
|
-
const response = await fetch(urlString, {
|
39
|
-
method: 'GET',
|
40
|
-
headers,
|
41
|
-
credentials: 'include' // 세션 쿠키/인증 정보 포함
|
42
|
-
});
|
43
|
-
if (!response.ok) {
|
44
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
45
|
-
}
|
46
|
-
const contentType = response.headers.get('content-type') || '';
|
47
|
-
if (contentType.includes('application/json')) {
|
48
|
-
return await response.json();
|
49
|
-
}
|
50
|
-
else if (contentType.includes('text/')) {
|
51
|
-
return await response.text();
|
52
|
-
}
|
53
|
-
else {
|
54
|
-
// Binary data나 기타 타입의 경우
|
55
|
-
const arrayBuffer = await response.arrayBuffer();
|
56
|
-
return Array.from(new Uint8Array(arrayBuffer));
|
57
|
-
}
|
58
|
-
}, requestUrl.toString(), headers);
|
9
|
+
const result = await (0, headless_request_with_recovery_1.executeHeadlessRequestWithRecovery)(connectionName, {
|
10
|
+
method: 'GET',
|
11
|
+
path,
|
12
|
+
headers: requestHeaders,
|
13
|
+
queryParams,
|
14
|
+
maxRetries: 2
|
15
|
+
}, { logger, data, domain });
|
59
16
|
return {
|
60
|
-
data:
|
17
|
+
data: result.data
|
61
18
|
};
|
62
19
|
}
|
63
20
|
catch (error) {
|
64
21
|
logger.error('Error in HeadlessGet:', error);
|
65
22
|
throw error;
|
66
23
|
}
|
67
|
-
finally {
|
68
|
-
await releasePage(page);
|
69
|
-
}
|
70
24
|
}
|
71
25
|
HeadlessGet.parameterSpec = [
|
72
26
|
{
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"headless-get.js","sourceRoot":"","sources":["../../../server/engine/task/headless-get.ts"],"names":[],"mappings":";;AAAA,
|
1
|
+
{"version":3,"file":"headless-get.js","sourceRoot":"","sources":["../../../server/engine/task/headless-get.ts"],"names":[],"mappings":";;AAAA,oDAA+C;AAC/C,2FAA2F;AAE3F,KAAK,UAAU,WAAW,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;IACvD,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAA;IAChE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,WAAW,IAAI,EAAE,CAAA;IAExE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAA,mEAAkC,EACrD,cAAc,EACd;YACE,MAAM,EAAE,KAAK;YACb,IAAI;YACJ,OAAO,EAAE,cAAc;YACvB,WAAW;YACX,UAAU,EAAE,CAAC;SACd,EACD,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CACzB,CAAA;QAED,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;SAClB,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAA;QAC5C,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC;AAED,WAAW,CAAC,aAAa,GAAG;IAC1B;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,MAAM;KACd;IACD;QACE,IAAI,EAAE,cAAc;QACpB,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;KACjB;IACD;QACE,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,kBAAkB;KAC1B;CACF,CAAA;AAED,4BAAY,CAAC,mBAAmB,CAAC,cAAc,EAAE,WAAW,CAAC,CAAA","sourcesContent":["import { TaskRegistry } from '../task-registry'\nimport { executeHeadlessRequestWithRecovery } from './utils/headless-request-with-recovery'\n\nasync function HeadlessGet(step, { logger, data, domain }) {\n const { connection: connectionName, params: stepOptions } = step\n const { headers: requestHeaders, path, queryParams } = stepOptions || {}\n\n try {\n const result = await executeHeadlessRequestWithRecovery(\n connectionName,\n {\n method: 'GET',\n path,\n headers: requestHeaders,\n queryParams,\n maxRetries: 2\n },\n { logger, data, domain }\n )\n\n return {\n data: result.data\n }\n } catch (error) {\n logger.error('Error in HeadlessGet:', error)\n throw error\n }\n}\n\nHeadlessGet.parameterSpec = [\n {\n type: 'string',\n name: 'path',\n label: 'path'\n },\n {\n type: 'http-headers',\n name: 'headers',\n label: 'headers'\n },\n {\n type: 'options',\n name: 'queryParams',\n label: 'query-parameters'\n }\n]\n\nTaskRegistry.registerTaskHandler('headless-get', HeadlessGet)\n"]}
|
@@ -1,91 +1,28 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
const url_1 = require("url");
|
4
|
-
const utils_1 = require("@things-factory/utils");
|
5
3
|
const task_registry_1 = require("../task-registry");
|
6
|
-
const
|
4
|
+
const headless_request_with_recovery_1 = require("./utils/headless-request-with-recovery");
|
7
5
|
async function HeadlessPatch(step, { logger, data, domain }) {
|
8
6
|
const { connection: connectionName, params: stepOptions } = step;
|
9
7
|
const { headers: requestHeaders, contentType, path, accessor, queryParams } = stepOptions || {};
|
10
|
-
const connection = await connection_manager_1.ConnectionManager.getConnectionInstanceByName(domain, connectionName);
|
11
|
-
if (!connection) {
|
12
|
-
throw new Error(`Connection '${connectionName}' is not established.`);
|
13
|
-
}
|
14
|
-
const { endpoint, params: connectionParams, acquireSessionPage, releasePage } = connection;
|
15
|
-
const headers = {
|
16
|
-
...requestHeaders
|
17
|
-
};
|
18
|
-
let body = (0, utils_1.access)(accessor, data);
|
19
|
-
if (contentType && body) {
|
20
|
-
headers['content-type'] = contentType;
|
21
|
-
switch (contentType) {
|
22
|
-
case 'text/plain':
|
23
|
-
body = JSON.stringify(body);
|
24
|
-
break;
|
25
|
-
case 'application/json':
|
26
|
-
body = JSON.stringify(body);
|
27
|
-
break;
|
28
|
-
case 'application/x-www-form-urlencoded':
|
29
|
-
const searchParams = new URLSearchParams();
|
30
|
-
for (const prop in body) {
|
31
|
-
searchParams.set(prop, body[prop]);
|
32
|
-
}
|
33
|
-
body = searchParams.toString();
|
34
|
-
break;
|
35
|
-
}
|
36
|
-
}
|
37
|
-
const page = await acquireSessionPage();
|
38
8
|
try {
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
Object.keys(queryParams).forEach(key => {
|
49
|
-
if (queryParams[key] !== null && queryParams[key] !== undefined) {
|
50
|
-
requestUrl.searchParams.append(key, String(queryParams[key]));
|
51
|
-
}
|
52
|
-
});
|
53
|
-
}
|
54
|
-
// headless-scrap과 동일한 방식으로 페이지 이동하여 세션 유지
|
55
|
-
await page.goto(requestUrl, { waitUntil: 'networkidle2' });
|
56
|
-
// 페이지 내에서 PATCH 요청 실행 (세션 유지)
|
57
|
-
const response = await page.evaluate(async (urlString, options) => {
|
58
|
-
const response = await fetch(urlString, {
|
59
|
-
...options,
|
60
|
-
credentials: 'include' // 세션 쿠키/인증 정보 포함
|
61
|
-
});
|
62
|
-
if (!response.ok) {
|
63
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
64
|
-
}
|
65
|
-
const contentType = response.headers.get('content-type') || '';
|
66
|
-
if (contentType.includes('application/json')) {
|
67
|
-
return await response.json();
|
68
|
-
}
|
69
|
-
else if (contentType.includes('text/')) {
|
70
|
-
return await response.text();
|
71
|
-
}
|
72
|
-
else {
|
73
|
-
// Binary data나 기타 타입의 경우
|
74
|
-
const arrayBuffer = await response.arrayBuffer();
|
75
|
-
return Array.from(new Uint8Array(arrayBuffer));
|
76
|
-
}
|
77
|
-
}, requestUrl.toString(), { method: 'PATCH', headers, body });
|
9
|
+
const result = await (0, headless_request_with_recovery_1.executeHeadlessRequestWithRecovery)(connectionName, {
|
10
|
+
method: 'PATCH',
|
11
|
+
path,
|
12
|
+
headers: requestHeaders,
|
13
|
+
queryParams,
|
14
|
+
maxRetries: 2,
|
15
|
+
accessor,
|
16
|
+
contentType
|
17
|
+
}, { logger, data, domain });
|
78
18
|
return {
|
79
|
-
data:
|
19
|
+
data: result.data
|
80
20
|
};
|
81
21
|
}
|
82
22
|
catch (error) {
|
83
23
|
logger.error('Error in HeadlessPatch:', error);
|
84
24
|
throw error;
|
85
25
|
}
|
86
|
-
finally {
|
87
|
-
await releasePage(page);
|
88
|
-
}
|
89
26
|
}
|
90
27
|
HeadlessPatch.parameterSpec = [
|
91
28
|
{
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"headless-patch.js","sourceRoot":"","sources":["../../../server/engine/task/headless-patch.ts"],"names":[],"mappings":";;AAAA,
|
1
|
+
{"version":3,"file":"headless-patch.js","sourceRoot":"","sources":["../../../server/engine/task/headless-patch.ts"],"names":[],"mappings":";;AAAA,oDAA+C;AAC/C,2FAA2F;AAE3F,KAAK,UAAU,aAAa,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;IACzD,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAA;IAChE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,WAAW,IAAI,EAAE,CAAA;IAE/F,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAA,mEAAkC,EACrD,cAAc,EACd;YACE,MAAM,EAAE,OAAO;YACf,IAAI;YACJ,OAAO,EAAE,cAAc;YACvB,WAAW;YACX,UAAU,EAAE,CAAC;YACb,QAAQ;YACR,WAAW;SACZ,EACD,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CACzB,CAAA;QAED,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;SAClB,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAA;QAC9C,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC;AAED,aAAa,CAAC,aAAa,GAAG;IAC5B;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,MAAM;KACd;IACD;QACE,IAAI,EAAE,cAAc;QACpB,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;KACjB;IACD;QACE,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,kBAAkB;KAC1B;IACD;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,cAAc;QACrB,QAAQ,EAAE;YACR,OAAO,EAAE;gBACP,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;gBAC1B,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,kBAAkB,EAAE;gBAC1D,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE;gBAC9C,EAAE,OAAO,EAAE,mCAAmC,EAAE,KAAK,EAAE,mCAAmC,EAAE;aAC7F;SACF;KACF;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,UAAU;KAClB;CACF,CAAA;AAED,4BAAY,CAAC,mBAAmB,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAA","sourcesContent":["import { TaskRegistry } from '../task-registry'\nimport { executeHeadlessRequestWithRecovery } from './utils/headless-request-with-recovery'\n\nasync function HeadlessPatch(step, { logger, data, domain }) {\n const { connection: connectionName, params: stepOptions } = step\n const { headers: requestHeaders, contentType, path, accessor, queryParams } = stepOptions || {}\n\n try {\n const result = await executeHeadlessRequestWithRecovery(\n connectionName,\n {\n method: 'PATCH',\n path,\n headers: requestHeaders,\n queryParams,\n maxRetries: 2,\n accessor,\n contentType\n },\n { logger, data, domain }\n )\n\n return {\n data: result.data\n }\n } catch (error) {\n logger.error('Error in HeadlessPatch:', error)\n throw error\n }\n}\n\nHeadlessPatch.parameterSpec = [\n {\n type: 'string',\n name: 'path',\n label: 'path'\n },\n {\n type: 'http-headers',\n name: 'headers',\n label: 'headers'\n },\n {\n type: 'options',\n name: 'queryParams',\n label: 'query-parameters'\n },\n {\n type: 'select',\n name: 'contentType',\n label: 'content-type',\n property: {\n options: [\n { display: '', value: '' },\n { display: 'application/json', value: 'application/json' },\n { display: 'text/plain', value: 'text/plain' },\n { display: 'application/x-www-form-urlencoded', value: 'application/x-www-form-urlencoded' }\n ]\n }\n },\n {\n type: 'scenario-step-input',\n name: 'accessor',\n label: 'accessor'\n }\n]\n\nTaskRegistry.registerTaskHandler('headless-patch', HeadlessPatch)\n"]}
|
@@ -1,91 +1,28 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
const url_1 = require("url");
|
4
|
-
const utils_1 = require("@things-factory/utils");
|
5
3
|
const task_registry_1 = require("../task-registry");
|
6
|
-
const
|
4
|
+
const headless_request_with_recovery_1 = require("./utils/headless-request-with-recovery");
|
7
5
|
async function HeadlessPost(step, { logger, data, domain }) {
|
8
6
|
const { connection: connectionName, params: stepOptions } = step;
|
9
7
|
const { headers: requestHeaders, contentType, path, accessor, queryParams } = stepOptions || {};
|
10
|
-
const connection = await connection_manager_1.ConnectionManager.getConnectionInstanceByName(domain, connectionName);
|
11
|
-
if (!connection) {
|
12
|
-
throw new Error(`Connection '${connectionName}' is not established.`);
|
13
|
-
}
|
14
|
-
const { endpoint, params: connectionParams, acquireSessionPage, releasePage } = connection;
|
15
|
-
const headers = {
|
16
|
-
...requestHeaders
|
17
|
-
};
|
18
|
-
let body = (0, utils_1.access)(accessor, data);
|
19
|
-
if (contentType && body) {
|
20
|
-
headers['content-type'] = contentType;
|
21
|
-
switch (contentType) {
|
22
|
-
case 'text/plain':
|
23
|
-
body = JSON.stringify(body);
|
24
|
-
break;
|
25
|
-
case 'application/json':
|
26
|
-
body = JSON.stringify(body);
|
27
|
-
break;
|
28
|
-
case 'application/x-www-form-urlencoded':
|
29
|
-
const searchParams = new URLSearchParams();
|
30
|
-
for (const prop in body) {
|
31
|
-
searchParams.set(prop, body[prop]);
|
32
|
-
}
|
33
|
-
body = searchParams.toString();
|
34
|
-
break;
|
35
|
-
}
|
36
|
-
}
|
37
|
-
const page = await acquireSessionPage();
|
38
8
|
try {
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
Object.keys(queryParams).forEach(key => {
|
49
|
-
if (queryParams[key] !== null && queryParams[key] !== undefined) {
|
50
|
-
requestUrl.searchParams.append(key, String(queryParams[key]));
|
51
|
-
}
|
52
|
-
});
|
53
|
-
}
|
54
|
-
// headless-scrap과 동일한 방식으로 페이지 이동하여 세션 유지
|
55
|
-
await page.goto(requestUrl, { waitUntil: 'networkidle2' });
|
56
|
-
// 페이지 내에서 POST 요청 실행 (세션 유지)
|
57
|
-
const response = await page.evaluate(async (urlString, options) => {
|
58
|
-
const response = await fetch(urlString, {
|
59
|
-
...options,
|
60
|
-
credentials: 'include' // 세션 쿠키/인증 정보 포함
|
61
|
-
});
|
62
|
-
if (!response.ok) {
|
63
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
64
|
-
}
|
65
|
-
const contentType = response.headers.get('content-type') || '';
|
66
|
-
if (contentType.includes('application/json')) {
|
67
|
-
return await response.json();
|
68
|
-
}
|
69
|
-
else if (contentType.includes('text/')) {
|
70
|
-
return await response.text();
|
71
|
-
}
|
72
|
-
else {
|
73
|
-
// Binary data나 기타 타입의 경우
|
74
|
-
const arrayBuffer = await response.arrayBuffer();
|
75
|
-
return Array.from(new Uint8Array(arrayBuffer));
|
76
|
-
}
|
77
|
-
}, requestUrl.toString(), { method: 'POST', headers, body });
|
9
|
+
const result = await (0, headless_request_with_recovery_1.executeHeadlessRequestWithRecovery)(connectionName, {
|
10
|
+
method: 'POST',
|
11
|
+
path,
|
12
|
+
headers: requestHeaders,
|
13
|
+
queryParams,
|
14
|
+
maxRetries: 2,
|
15
|
+
accessor,
|
16
|
+
contentType
|
17
|
+
}, { logger, data, domain });
|
78
18
|
return {
|
79
|
-
data:
|
19
|
+
data: result.data
|
80
20
|
};
|
81
21
|
}
|
82
22
|
catch (error) {
|
83
23
|
logger.error('Error in HeadlessPost:', error);
|
84
24
|
throw error;
|
85
25
|
}
|
86
|
-
finally {
|
87
|
-
await releasePage(page);
|
88
|
-
}
|
89
26
|
}
|
90
27
|
HeadlessPost.parameterSpec = [
|
91
28
|
{
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"headless-post.js","sourceRoot":"","sources":["../../../server/engine/task/headless-post.ts"],"names":[],"mappings":";;AAAA,
|
1
|
+
{"version":3,"file":"headless-post.js","sourceRoot":"","sources":["../../../server/engine/task/headless-post.ts"],"names":[],"mappings":";;AAAA,oDAA+C;AAC/C,2FAA2F;AAE3F,KAAK,UAAU,YAAY,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;IACxD,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAA;IAChE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,WAAW,IAAI,EAAE,CAAA;IAE/F,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAA,mEAAkC,EACrD,cAAc,EACd;YACE,MAAM,EAAE,MAAM;YACd,IAAI;YACJ,OAAO,EAAE,cAAc;YACvB,WAAW;YACX,UAAU,EAAE,CAAC;YACb,QAAQ;YACR,WAAW;SACZ,EACD,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CACzB,CAAA;QAED,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;SAClB,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAA;QAC7C,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC;AAED,YAAY,CAAC,aAAa,GAAG;IAC3B;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,MAAM;KACd;IACD;QACE,IAAI,EAAE,cAAc;QACpB,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;KACjB;IACD;QACE,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,kBAAkB;KAC1B;IACD;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,cAAc;QACrB,QAAQ,EAAE;YACR,OAAO,EAAE;gBACP,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;gBAC1B,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,kBAAkB,EAAE;gBAC1D,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE;gBAC9C,EAAE,OAAO,EAAE,mCAAmC,EAAE,KAAK,EAAE,mCAAmC,EAAE;aAC7F;SACF;KACF;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,UAAU;KAClB;CACF,CAAA;AAED,4BAAY,CAAC,mBAAmB,CAAC,eAAe,EAAE,YAAY,CAAC,CAAA","sourcesContent":["import { TaskRegistry } from '../task-registry'\nimport { executeHeadlessRequestWithRecovery } from './utils/headless-request-with-recovery'\n\nasync function HeadlessPost(step, { logger, data, domain }) {\n const { connection: connectionName, params: stepOptions } = step\n const { headers: requestHeaders, contentType, path, accessor, queryParams } = stepOptions || {}\n\n try {\n const result = await executeHeadlessRequestWithRecovery(\n connectionName,\n {\n method: 'POST',\n path,\n headers: requestHeaders,\n queryParams,\n maxRetries: 2,\n accessor,\n contentType\n },\n { logger, data, domain }\n )\n\n return {\n data: result.data\n }\n } catch (error) {\n logger.error('Error in HeadlessPost:', error)\n throw error\n }\n}\n\nHeadlessPost.parameterSpec = [\n {\n type: 'string',\n name: 'path',\n label: 'path'\n },\n {\n type: 'http-headers',\n name: 'headers',\n label: 'headers'\n },\n {\n type: 'options',\n name: 'queryParams',\n label: 'query-parameters'\n },\n {\n type: 'select',\n name: 'contentType',\n label: 'content-type',\n property: {\n options: [\n { display: '', value: '' },\n { display: 'application/json', value: 'application/json' },\n { display: 'text/plain', value: 'text/plain' },\n { display: 'application/x-www-form-urlencoded', value: 'application/x-www-form-urlencoded' }\n ]\n }\n },\n {\n type: 'scenario-step-input',\n name: 'accessor',\n label: 'accessor'\n }\n]\n\nTaskRegistry.registerTaskHandler('headless-post', HeadlessPost)\n"]}
|
@@ -1,91 +1,28 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
const url_1 = require("url");
|
4
|
-
const utils_1 = require("@things-factory/utils");
|
5
3
|
const task_registry_1 = require("../task-registry");
|
6
|
-
const
|
4
|
+
const headless_request_with_recovery_1 = require("./utils/headless-request-with-recovery");
|
7
5
|
async function HeadlessPut(step, { logger, data, domain }) {
|
8
6
|
const { connection: connectionName, params: stepOptions } = step;
|
9
7
|
const { headers: requestHeaders, contentType, path, accessor, queryParams } = stepOptions || {};
|
10
|
-
const connection = await connection_manager_1.ConnectionManager.getConnectionInstanceByName(domain, connectionName);
|
11
|
-
if (!connection) {
|
12
|
-
throw new Error(`Connection '${connectionName}' is not established.`);
|
13
|
-
}
|
14
|
-
const { endpoint, params: connectionParams, acquireSessionPage, releasePage } = connection;
|
15
|
-
const headers = {
|
16
|
-
...requestHeaders
|
17
|
-
};
|
18
|
-
let body = (0, utils_1.access)(accessor, data);
|
19
|
-
if (contentType && body) {
|
20
|
-
headers['content-type'] = contentType;
|
21
|
-
switch (contentType) {
|
22
|
-
case 'text/plain':
|
23
|
-
body = JSON.stringify(body);
|
24
|
-
break;
|
25
|
-
case 'application/json':
|
26
|
-
body = JSON.stringify(body);
|
27
|
-
break;
|
28
|
-
case 'application/x-www-form-urlencoded':
|
29
|
-
const searchParams = new URLSearchParams();
|
30
|
-
for (const prop in body) {
|
31
|
-
searchParams.set(prop, body[prop]);
|
32
|
-
}
|
33
|
-
body = searchParams.toString();
|
34
|
-
break;
|
35
|
-
}
|
36
|
-
}
|
37
|
-
const page = await acquireSessionPage();
|
38
8
|
try {
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
Object.keys(queryParams).forEach(key => {
|
49
|
-
if (queryParams[key] !== null && queryParams[key] !== undefined) {
|
50
|
-
requestUrl.searchParams.append(key, String(queryParams[key]));
|
51
|
-
}
|
52
|
-
});
|
53
|
-
}
|
54
|
-
// headless-scrap과 동일한 방식으로 페이지 이동하여 세션 유지
|
55
|
-
await page.goto(requestUrl, { waitUntil: 'networkidle2' });
|
56
|
-
// 페이지 내에서 PUT 요청 실행 (세션 유지)
|
57
|
-
const response = await page.evaluate(async (urlString, options) => {
|
58
|
-
const response = await fetch(urlString, {
|
59
|
-
...options,
|
60
|
-
credentials: 'include' // 세션 쿠키/인증 정보 포함
|
61
|
-
});
|
62
|
-
if (!response.ok) {
|
63
|
-
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
64
|
-
}
|
65
|
-
const contentType = response.headers.get('content-type') || '';
|
66
|
-
if (contentType.includes('application/json')) {
|
67
|
-
return await response.json();
|
68
|
-
}
|
69
|
-
else if (contentType.includes('text/')) {
|
70
|
-
return await response.text();
|
71
|
-
}
|
72
|
-
else {
|
73
|
-
// Binary data나 기타 타입의 경우
|
74
|
-
const arrayBuffer = await response.arrayBuffer();
|
75
|
-
return Array.from(new Uint8Array(arrayBuffer));
|
76
|
-
}
|
77
|
-
}, requestUrl.toString(), { method: 'PUT', headers, body });
|
9
|
+
const result = await (0, headless_request_with_recovery_1.executeHeadlessRequestWithRecovery)(connectionName, {
|
10
|
+
method: 'PUT',
|
11
|
+
path,
|
12
|
+
headers: requestHeaders,
|
13
|
+
queryParams,
|
14
|
+
maxRetries: 2,
|
15
|
+
accessor,
|
16
|
+
contentType
|
17
|
+
}, { logger, data, domain });
|
78
18
|
return {
|
79
|
-
data:
|
19
|
+
data: result.data
|
80
20
|
};
|
81
21
|
}
|
82
22
|
catch (error) {
|
83
23
|
logger.error('Error in HeadlessPut:', error);
|
84
24
|
throw error;
|
85
25
|
}
|
86
|
-
finally {
|
87
|
-
await releasePage(page);
|
88
|
-
}
|
89
26
|
}
|
90
27
|
HeadlessPut.parameterSpec = [
|
91
28
|
{
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"headless-put.js","sourceRoot":"","sources":["../../../server/engine/task/headless-put.ts"],"names":[],"mappings":";;AAAA,
|
1
|
+
{"version":3,"file":"headless-put.js","sourceRoot":"","sources":["../../../server/engine/task/headless-put.ts"],"names":[],"mappings":";;AAAA,oDAA+C;AAC/C,2FAA2F;AAE3F,KAAK,UAAU,WAAW,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE;IACvD,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAA;IAChE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,WAAW,IAAI,EAAE,CAAA;IAE/F,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAA,mEAAkC,EACrD,cAAc,EACd;YACE,MAAM,EAAE,KAAK;YACb,IAAI;YACJ,OAAO,EAAE,cAAc;YACvB,WAAW;YACX,UAAU,EAAE,CAAC;YACb,QAAQ;YACR,WAAW;SACZ,EACD,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CACzB,CAAA;QAED,OAAO;YACL,IAAI,EAAE,MAAM,CAAC,IAAI;SAClB,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAA;QAC5C,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC;AAED,WAAW,CAAC,aAAa,GAAG;IAC1B;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,MAAM;KACd;IACD;QACE,IAAI,EAAE,cAAc;QACpB,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;KACjB;IACD;QACE,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,kBAAkB;KAC1B;IACD;QACE,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,cAAc;QACrB,QAAQ,EAAE;YACR,OAAO,EAAE;gBACP,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;gBAC1B,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,kBAAkB,EAAE;gBAC1D,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE;gBAC9C,EAAE,OAAO,EAAE,mCAAmC,EAAE,KAAK,EAAE,mCAAmC,EAAE;aAC7F;SACF;KACF;IACD;QACE,IAAI,EAAE,qBAAqB;QAC3B,IAAI,EAAE,UAAU;QAChB,KAAK,EAAE,UAAU;KAClB;CACF,CAAA;AAED,4BAAY,CAAC,mBAAmB,CAAC,cAAc,EAAE,WAAW,CAAC,CAAA","sourcesContent":["import { TaskRegistry } from '../task-registry'\nimport { executeHeadlessRequestWithRecovery } from './utils/headless-request-with-recovery'\n\nasync function HeadlessPut(step, { logger, data, domain }) {\n const { connection: connectionName, params: stepOptions } = step\n const { headers: requestHeaders, contentType, path, accessor, queryParams } = stepOptions || {}\n\n try {\n const result = await executeHeadlessRequestWithRecovery(\n connectionName,\n {\n method: 'PUT',\n path,\n headers: requestHeaders,\n queryParams,\n maxRetries: 2,\n accessor,\n contentType\n },\n { logger, data, domain }\n )\n\n return {\n data: result.data\n }\n } catch (error) {\n logger.error('Error in HeadlessPut:', error)\n throw error\n }\n}\n\nHeadlessPut.parameterSpec = [\n {\n type: 'string',\n name: 'path',\n label: 'path'\n },\n {\n type: 'http-headers',\n name: 'headers',\n label: 'headers'\n },\n {\n type: 'options',\n name: 'queryParams',\n label: 'query-parameters'\n },\n {\n type: 'select',\n name: 'contentType',\n label: 'content-type',\n property: {\n options: [\n { display: '', value: '' },\n { display: 'application/json', value: 'application/json' },\n { display: 'text/plain', value: 'text/plain' },\n { display: 'application/x-www-form-urlencoded', value: 'application/x-www-form-urlencoded' }\n ]\n }\n },\n {\n type: 'scenario-step-input',\n name: 'accessor',\n label: 'accessor'\n }\n]\n\nTaskRegistry.registerTaskHandler('headless-put', HeadlessPut)\n"]}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
export interface HeadlessRequestOptions {
|
2
|
+
method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
3
|
+
path: string;
|
4
|
+
headers?: Record<string, string>;
|
5
|
+
body?: any;
|
6
|
+
queryParams?: Record<string, any>;
|
7
|
+
maxRetries?: number;
|
8
|
+
accessor?: string;
|
9
|
+
contentType?: string;
|
10
|
+
}
|
11
|
+
/**
|
12
|
+
* 세션 회복 기능을 포함한 headless HTTP 요청 함수
|
13
|
+
*/
|
14
|
+
export declare function executeHeadlessRequestWithRecovery(connectionName: string, options: HeadlessRequestOptions, context: {
|
15
|
+
logger: any;
|
16
|
+
data: any;
|
17
|
+
domain: any;
|
18
|
+
}): Promise<any>;
|