@speedkit/cli 3.5.1 → 3.6.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 +8 -0
- package/README.md +1 -1
- package/dist/services/document-handler-runtime/server/document-handler-response.d.ts +1 -1
- package/dist/services/document-handler-runtime/server/request.d.ts +2 -0
- package/dist/services/document-handler-runtime/server/request.js +6 -5
- package/dist/services/onboarding/browser/baqend-response.d.ts +1 -1
- package/dist/services/onboarding/browser/baqend-response.js +3 -1
- package/dist/services/onboarding/browser/extension/extension-downloader.d.ts +1 -1
- package/dist/services/onboarding/browser/extension/extension-downloader.js +4 -3
- package/dist/services/onboarding/browser/extension/extension-validator.js +15 -6
- package/dist/services/onboarding/browser/origin-response.d.ts +2 -2
- package/dist/services/onboarding/browser/origin-response.js +4 -3
- package/dist/services/onboarding/dashboard/diff-against-current-page.js +10 -2
- package/dist/services/onboarding/dashboard/request-diff-service.js +6 -0
- package/dist/services/onboarding/error/validate-extension-error.d.ts +5 -0
- package/dist/services/onboarding/error/validate-extension-error.js +12 -0
- package/dist/services/onboarding/fetch-events/customer-domain-document-response.js +39 -20
- package/dist/services/onboarding/virtual-orestes-app/index.js +36 -16
- package/oclif.manifest.json +1 -1
- package/package.json +6 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
# [3.6.0](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v3.5.1...v3.6.0) (2025-09-02)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **onboarding:** implement dynamic encoding for documentHandling ([290cf82](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/290cf8267208eeb577698001b3a5e9d48524eb66))
|
|
7
|
+
* **onboarding:** overwrite content-type header for docHandlerRequest ([cfba8d6](https://gitlab.orestes.info/baqend/speed-kit-cli/commit/cfba8d69db47dcfb193c2d796451783d01f72f59))
|
|
8
|
+
|
|
1
9
|
## [3.5.1](https://gitlab.orestes.info/baqend/speed-kit-cli/compare/v3.5.0...v3.5.1) (2025-08-26)
|
|
2
10
|
|
|
3
11
|
|
package/README.md
CHANGED
|
@@ -4,11 +4,13 @@ type query = {
|
|
|
4
4
|
headers: string;
|
|
5
5
|
};
|
|
6
6
|
export declare class Request {
|
|
7
|
+
private headers;
|
|
7
8
|
query: query;
|
|
8
9
|
body: string;
|
|
9
10
|
constructor(url: string, body: string, variation: string, headers: {
|
|
10
11
|
[name: string]: string;
|
|
11
12
|
});
|
|
12
13
|
get(key: string): string | null;
|
|
14
|
+
header(key: string): string | null;
|
|
13
15
|
}
|
|
14
16
|
export {};
|
|
@@ -2,18 +2,19 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Request = void 0;
|
|
4
4
|
class Request {
|
|
5
|
+
headers;
|
|
5
6
|
query;
|
|
6
7
|
body;
|
|
7
8
|
constructor(url, body, variation, headers) {
|
|
9
|
+
this.headers = headers;
|
|
8
10
|
this.query = { variation, headers: JSON.stringify(headers), url };
|
|
9
11
|
this.body = body;
|
|
10
12
|
}
|
|
11
13
|
get(key) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return this.query.headers[foundKey];
|
|
14
|
+
return this.headers?.[key] || null;
|
|
15
|
+
}
|
|
16
|
+
header(key) {
|
|
17
|
+
return this.get(key);
|
|
17
18
|
}
|
|
18
19
|
}
|
|
19
20
|
exports.Request = Request;
|
|
@@ -6,7 +6,7 @@ export declare class BaqendResponse implements Partial<Protocol.Fetch.FulfillReq
|
|
|
6
6
|
responseHeaders: Protocol.Fetch.HeaderEntry[];
|
|
7
7
|
private readonly contentType;
|
|
8
8
|
private readonly contentLength;
|
|
9
|
-
constructor(body: string, contentType?: string, headers?: Protocol.Fetch.HeaderEntry[], status?: number);
|
|
9
|
+
constructor(body: string | Buffer, contentType?: string, headers?: Protocol.Fetch.HeaderEntry[], status?: number);
|
|
10
10
|
setHeader(name: string, value: string): void;
|
|
11
11
|
protected addCustomHeaders(headers?: Protocol.Fetch.HeaderEntry[]): Protocol.Fetch.HeaderEntry[];
|
|
12
12
|
}
|
|
@@ -22,7 +22,9 @@ class BaqendResponse {
|
|
|
22
22
|
...DEFAULT_HEADERS,
|
|
23
23
|
...(headers || []),
|
|
24
24
|
]);
|
|
25
|
-
this.body = Buffer.
|
|
25
|
+
this.body = Buffer.isBuffer(body)
|
|
26
|
+
? body.toString("base64")
|
|
27
|
+
: Buffer.from(body).toString("base64");
|
|
26
28
|
}
|
|
27
29
|
setHeader(name, value) {
|
|
28
30
|
for (const header of this.responseHeaders) {
|
|
@@ -4,7 +4,7 @@ export declare class ExtensionDownloader {
|
|
|
4
4
|
private userConfig;
|
|
5
5
|
private cli;
|
|
6
6
|
constructor(userConfig: UserCliConfig, cli: CliServiceInterface);
|
|
7
|
-
downloadExtension(): Promise<string
|
|
7
|
+
downloadExtension(): Promise<string>;
|
|
8
8
|
private updateLocalDevtools;
|
|
9
9
|
isInstalled(): boolean;
|
|
10
10
|
private checkInstalledVersion;
|
|
@@ -8,6 +8,7 @@ const semver_1 = tslib_1.__importDefault(require("semver"));
|
|
|
8
8
|
const extract_zip_1 = tslib_1.__importDefault(require("extract-zip"));
|
|
9
9
|
const cli_1 = require("../../../cli");
|
|
10
10
|
const safe_1 = require("../../../../helpers/safe");
|
|
11
|
+
const validate_extension_error_1 = require("../../error/validate-extension-error");
|
|
11
12
|
const devtools = "integration-devtools";
|
|
12
13
|
class ExtensionDownloader {
|
|
13
14
|
userConfig;
|
|
@@ -26,14 +27,14 @@ class ExtensionDownloader {
|
|
|
26
27
|
if (semver_1.default.compare(remoteVersion, localVersion) > 0) {
|
|
27
28
|
const response = await this.cli.confirm(`integration-devtools update available from ${localVersion} to ${remoteVersion} Install?`, true);
|
|
28
29
|
if (!response) {
|
|
29
|
-
|
|
30
|
+
throw new validate_extension_error_1.ValidateExtensionError(localVersion, remoteVersion);
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
33
|
}
|
|
33
34
|
else {
|
|
34
35
|
const response = await this.cli.confirm("Do you want to install devtools-extension?", true);
|
|
35
36
|
if (!response) {
|
|
36
|
-
return
|
|
37
|
+
return;
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
this.cli.startAction("update integration-devtools");
|
|
@@ -41,7 +42,7 @@ class ExtensionDownloader {
|
|
|
41
42
|
if (response.success === false) {
|
|
42
43
|
this.cli.endAction(cli_1.CliActionStatus.FAILED);
|
|
43
44
|
this.cli.writeError(response.error);
|
|
44
|
-
return
|
|
45
|
+
return;
|
|
45
46
|
}
|
|
46
47
|
this.cli.endAction(cli_1.CliActionStatus.COMPLETED);
|
|
47
48
|
return response.data;
|
|
@@ -60,18 +60,27 @@ class ExtensionValidator {
|
|
|
60
60
|
return result.data;
|
|
61
61
|
}
|
|
62
62
|
async handleDevtoolsExtension(validExtensions) {
|
|
63
|
+
// check if devtools extension can be find in current extensionPaths
|
|
63
64
|
if (validExtensions.some((config) => config.name.toLowerCase().includes("devtools extension"))) {
|
|
64
65
|
return;
|
|
65
66
|
}
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
// download or update extension
|
|
68
|
+
const result = await (0, safe_1.safe)(this.extensionDownloader.downloadExtension());
|
|
69
|
+
if (result.success !== true) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (result.data?.length > 0) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// get extensionDetails from manifestFile
|
|
76
|
+
const extensionConfigResult = await (0, safe_1.safe)(this.getManifestConfig(result.data));
|
|
77
|
+
if (extensionConfigResult.success !== true) {
|
|
68
78
|
return;
|
|
69
79
|
}
|
|
70
|
-
const extensionConfig = await this.getManifestConfig(path);
|
|
71
80
|
validExtensions.push({
|
|
72
|
-
path:
|
|
73
|
-
name:
|
|
74
|
-
version:
|
|
81
|
+
path: result.data,
|
|
82
|
+
name: extensionConfigResult.data.name,
|
|
83
|
+
version: extensionConfigResult.data.version,
|
|
75
84
|
});
|
|
76
85
|
}
|
|
77
86
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import Protocol from "devtools-protocol";
|
|
2
2
|
export declare class OriginResponse implements Partial<Protocol.Fetch.FulfillRequestRequest> {
|
|
3
|
-
readonly body: string;
|
|
4
3
|
readonly responseCode: number;
|
|
5
4
|
readonly responseHeaders: Protocol.Fetch.HeaderEntry[];
|
|
6
|
-
|
|
5
|
+
readonly body: string;
|
|
6
|
+
constructor(body: string | Buffer, headers: Protocol.Fetch.HeaderEntry[], responseCode: number);
|
|
7
7
|
private addCustomHeaders;
|
|
8
8
|
}
|
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.OriginResponse = void 0;
|
|
4
4
|
class OriginResponse {
|
|
5
|
-
body;
|
|
6
5
|
responseCode;
|
|
7
6
|
responseHeaders;
|
|
7
|
+
body;
|
|
8
8
|
constructor(body, headers, responseCode) {
|
|
9
|
-
this.body = body;
|
|
10
9
|
this.responseCode = responseCode;
|
|
11
10
|
this.responseHeaders = this.addCustomHeaders(headers);
|
|
12
|
-
this.body = Buffer.
|
|
11
|
+
this.body = Buffer.isBuffer(body)
|
|
12
|
+
? body.toString("base64")
|
|
13
|
+
: Buffer.from(body).toString("base64");
|
|
13
14
|
}
|
|
14
15
|
addCustomHeaders(headers) {
|
|
15
16
|
headers.push({ name: "x-served-via", value: "sk-onboarding" }, { name: "Service-Worker-Allowed", value: "/" });
|
|
@@ -27,9 +27,17 @@ class DiffAgainstCurrentPage {
|
|
|
27
27
|
if (transform) {
|
|
28
28
|
// todo check if the currentHTML is already transformed
|
|
29
29
|
const currentDocumentHandlerResponse = await this.documentHandlerRuntime.transform(currentHtml, variant, currentUrl, {});
|
|
30
|
-
|
|
30
|
+
const currentResponse = currentDocumentHandlerResponse.body;
|
|
31
|
+
if (Buffer.isBuffer(currentResponse)) {
|
|
32
|
+
throw new TypeError("cant diff body as buffer");
|
|
33
|
+
}
|
|
34
|
+
currentHtml = currentResponse;
|
|
31
35
|
const originDocumentHandlerResponse = await this.documentHandlerRuntime.transform(originHtml, variant, currentUrl, {});
|
|
32
|
-
|
|
36
|
+
const originResponse = originDocumentHandlerResponse.body;
|
|
37
|
+
if (Buffer.isBuffer(originResponse)) {
|
|
38
|
+
throw new TypeError("cant diff body as buffer");
|
|
39
|
+
}
|
|
40
|
+
originHtml = originResponse;
|
|
33
41
|
}
|
|
34
42
|
this.cli.endAction(cli_1.CliActionStatus.COMPLETED);
|
|
35
43
|
const remoteFilePath = await this.diffService.writeContentToTemporalFile(`remote-${variant}.html`, originHtml);
|
|
@@ -41,9 +41,15 @@ class RequestDiffService {
|
|
|
41
41
|
const replaceRegEx = /<meta[^>]*name="baqend:asset_url"[^>]*>/;
|
|
42
42
|
// <meta name="baqend:asset_url" content="https://www.kik.de/c/damen/damen-bekleidung-shirts-tops?page=7">
|
|
43
43
|
const transformedHtmlWithParameterResponse = await this.documentHandlerRuntime.transform(htmlWithParameter, "", urlWithParameter, {});
|
|
44
|
+
if (Buffer.isBuffer(transformedHtmlWithParameterResponse.body)) {
|
|
45
|
+
throw new TypeError("Can't diff body if it's a buffer");
|
|
46
|
+
}
|
|
44
47
|
let transformedHtmlWithParameter = transformedHtmlWithParameterResponse.body;
|
|
45
48
|
transformedHtmlWithParameter = transformedHtmlWithParameter.replace(replaceRegEx, "");
|
|
46
49
|
const transformedHtmlWithoutParameterResponse = await this.documentHandlerRuntime.transform(htmlWithoutParameter, "", urlWithParameter, {});
|
|
50
|
+
if (Buffer.isBuffer(transformedHtmlWithoutParameterResponse.body)) {
|
|
51
|
+
throw new TypeError("Can't diff body if it's a buffer");
|
|
52
|
+
}
|
|
47
53
|
let transformedHtmlWithoutParameter = transformedHtmlWithoutParameterResponse.body;
|
|
48
54
|
transformedHtmlWithoutParameter = transformedHtmlWithoutParameter.replace(replaceRegEx, "");
|
|
49
55
|
if (checkIsEqual) {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ValidateExtensionError = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const application_error_1 = tslib_1.__importDefault(require("../../error-handling/error/application-error"));
|
|
6
|
+
class ValidateExtensionError extends application_error_1.default {
|
|
7
|
+
code = "VALIDATE_EXTENSION_ERROR";
|
|
8
|
+
constructor(localVersion, remoteVersion) {
|
|
9
|
+
super(`Unable to validate Versions: "${localVersion}" - "${remoteVersion}"`);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.ValidateExtensionError = ValidateExtensionError;
|
|
@@ -5,7 +5,7 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const onboarding_model_1 = require("../onboarding-model");
|
|
6
6
|
const origin_response_1 = require("../browser/origin-response");
|
|
7
7
|
const iconv_lite_1 = tslib_1.__importDefault(require("iconv-lite"));
|
|
8
|
-
const
|
|
8
|
+
const encoding_japanese_1 = tslib_1.__importDefault(require("encoding-japanese"));
|
|
9
9
|
/**
|
|
10
10
|
* Intercepts any request to the customersOrigin and equivalent requests to baqendAssetApi
|
|
11
11
|
* @implements {FetchRequestPausedEventHandler}
|
|
@@ -62,33 +62,31 @@ class CustomerDomainDocumentResponse {
|
|
|
62
62
|
if (!this.isHtmlContentHeader(event.responseHeaders)) {
|
|
63
63
|
return;
|
|
64
64
|
}
|
|
65
|
-
|
|
66
|
-
return headerRecord.name.toLowerCase() === "content-type";
|
|
67
|
-
})?.["value"] || "";
|
|
68
|
-
const charset = contentType.split("charset=")?.[1]?.trim() || "utf-8";
|
|
69
|
-
let text = await this.getHtmlContent(client, event, charset);
|
|
65
|
+
let text = await this.getHtmlContent(client, event);
|
|
70
66
|
if (!this.isValidHtmlContent(text)) {
|
|
71
67
|
return;
|
|
72
68
|
}
|
|
69
|
+
const headers = this.removeContentSecurityPolicy
|
|
70
|
+
? this.removeContentSecurityHeaderFromResponse(event.responseHeaders)
|
|
71
|
+
: event.responseHeaders;
|
|
73
72
|
if (this.customerConfig.forceInstall) {
|
|
74
73
|
text = this.rewriteInstallResource(text);
|
|
75
74
|
}
|
|
76
75
|
if (this.isSpeedKitResponse(text)) {
|
|
77
76
|
text = this.rewriteHtmlToLocalConfig(text);
|
|
78
77
|
}
|
|
79
|
-
const headers = this.removeContentSecurityPolicy
|
|
80
|
-
? this.removeContentSecurityHeaderFromResponse(event.responseHeaders)
|
|
81
|
-
: event.responseHeaders;
|
|
82
78
|
const content = this.removeContentSecurityPolicy
|
|
83
79
|
? this.removeContentSecurityMetaTag(text)
|
|
84
80
|
: text;
|
|
85
81
|
// replace origin contentTypeCharset with utf-8 as this is what it's converted to now
|
|
82
|
+
let detectedEncoding = "utf-8";
|
|
86
83
|
for (const header of headers) {
|
|
87
|
-
if (header.name.
|
|
88
|
-
|
|
84
|
+
if (header.name.includes("x-sk-detected-encoding")) {
|
|
85
|
+
detectedEncoding = header.value;
|
|
89
86
|
}
|
|
90
87
|
}
|
|
91
|
-
|
|
88
|
+
const encodedContent = iconv_lite_1.default.encode(content, detectedEncoding);
|
|
89
|
+
return new origin_response_1.OriginResponse(encodedContent, headers, event.responseStatusCode);
|
|
92
90
|
}
|
|
93
91
|
isValidHtmlContent(text) {
|
|
94
92
|
return text.includes("<html");
|
|
@@ -105,20 +103,41 @@ class CustomerDomainDocumentResponse {
|
|
|
105
103
|
})?.["value"];
|
|
106
104
|
return contentType && contentType.includes("text/html");
|
|
107
105
|
}
|
|
108
|
-
async getHtmlContent(client, event
|
|
106
|
+
async getHtmlContent(client, event) {
|
|
109
107
|
const { body, base64Encoded } = await client.send("Fetch.getResponseBody", {
|
|
110
108
|
requestId: event.requestId,
|
|
111
109
|
});
|
|
110
|
+
const contentType = event.responseHeaders.find((headerRecord) => {
|
|
111
|
+
return headerRecord.name.toLowerCase() === "content-type";
|
|
112
|
+
})?.["value"] || "";
|
|
113
|
+
const charsetRegex = /charset=([^\s"(),./:;<=>?@[\]]*)/i;
|
|
114
|
+
const encodingFromHeader = contentType && charsetRegex.test(contentType)
|
|
115
|
+
? charsetRegex.exec(contentType)[1]
|
|
116
|
+
: null;
|
|
112
117
|
// create text from base64Encoded
|
|
113
118
|
if (base64Encoded) {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
+
const buffer = Buffer.from(body, "base64");
|
|
120
|
+
const encodingFromBuffer = encoding_japanese_1.default.detect(buffer);
|
|
121
|
+
const encodedBody = iconv_lite_1.default
|
|
122
|
+
.decode(buffer, encodingFromHeader ?? encodingFromBuffer)
|
|
123
|
+
.toString();
|
|
124
|
+
const metaSelector = /<meta http-equiv="content-type" content="text\/html;charset=([^\s"(),./:;<=>?@[\]]*)">/is;
|
|
125
|
+
const encodingFromBodyMeta = metaSelector.test(encodedBody)
|
|
126
|
+
? metaSelector.exec(encodedBody)[1]
|
|
127
|
+
: "";
|
|
128
|
+
const detectedEncoding = encodingFromHeader ||
|
|
129
|
+
encodingFromBodyMeta ||
|
|
130
|
+
encodingFromBuffer ||
|
|
131
|
+
"utf-8";
|
|
132
|
+
if (!iconv_lite_1.default.encodingExists(detectedEncoding)) {
|
|
133
|
+
console.error(`Encoding not supported: "${detectedEncoding}" on url: ${event.request.url}`);
|
|
134
|
+
return encodedBody;
|
|
119
135
|
}
|
|
120
|
-
|
|
121
|
-
|
|
136
|
+
event.responseHeaders.push({
|
|
137
|
+
name: "x-sk-detected-encoding",
|
|
138
|
+
value: detectedEncoding,
|
|
139
|
+
});
|
|
140
|
+
return iconv_lite_1.default.decode(buffer, detectedEncoding);
|
|
122
141
|
}
|
|
123
142
|
return body;
|
|
124
143
|
}
|
|
@@ -6,6 +6,8 @@ const baqend_response_1 = require("../browser/baqend-response");
|
|
|
6
6
|
const safe_1 = require("../../../helpers/safe");
|
|
7
7
|
const onboarding_model_1 = require("../onboarding-model");
|
|
8
8
|
const iconv_lite_1 = tslib_1.__importDefault(require("iconv-lite"));
|
|
9
|
+
const encoding_japanese_1 = tslib_1.__importDefault(require("encoding-japanese"));
|
|
10
|
+
const iconv_lite_2 = tslib_1.__importDefault(require("iconv-lite"));
|
|
9
11
|
class VirtualOrestesApp {
|
|
10
12
|
customerConfig;
|
|
11
13
|
crawler;
|
|
@@ -46,25 +48,28 @@ class VirtualOrestesApp {
|
|
|
46
48
|
if (response.status > 300 && response.status < 400) {
|
|
47
49
|
return this.returnRedirect(customHeaders, response, event);
|
|
48
50
|
}
|
|
49
|
-
const responseContent = await this.getResponseText(response);
|
|
51
|
+
const { responseContent, responseEncoding } = await this.getResponseText(response);
|
|
50
52
|
if (!this.isHtmlContentHeader(response.headers) ||
|
|
51
53
|
!this.isValidHtmlContent(responseContent)) {
|
|
52
|
-
const customResponse = new baqend_response_1.BaqendResponse(responseContent,
|
|
54
|
+
const customResponse = new baqend_response_1.BaqendResponse(responseContent, `text/html; charset=${responseEncoding}`, customHeaders);
|
|
53
55
|
this.cache.addEntry(event.request.url, customResponse);
|
|
54
56
|
return customResponse;
|
|
55
57
|
}
|
|
56
58
|
const convertedResponseHeaders = this.convertResponseHeadersToOrestesFormat(response);
|
|
57
|
-
const customResponse = await (0, safe_1.safe)(this.documentHandler.transform(responseContent, variation, originUrl,
|
|
59
|
+
const customResponse = await (0, safe_1.safe)(this.documentHandler.transform(responseContent, variation, originUrl, {
|
|
60
|
+
...convertedResponseHeaders,
|
|
61
|
+
"content-type": `text/html;charset=${responseEncoding}`,
|
|
62
|
+
}));
|
|
58
63
|
if (customResponse.success === false) {
|
|
59
64
|
return this.returnErrorResponse(customResponse, customHeaders);
|
|
60
65
|
}
|
|
61
66
|
const skResponse = customResponse.data;
|
|
62
|
-
if (this.customerConfig.forceInstall) {
|
|
67
|
+
if (!Buffer.isBuffer(skResponse.body) && this.customerConfig.forceInstall) {
|
|
63
68
|
skResponse.body = this.rewriteInstallResource(skResponse.body);
|
|
64
69
|
}
|
|
65
70
|
for (const key in skResponse.headers) {
|
|
66
71
|
customHeaders.push({
|
|
67
|
-
name:
|
|
72
|
+
name: key,
|
|
68
73
|
value: skResponse.headers[key],
|
|
69
74
|
});
|
|
70
75
|
}
|
|
@@ -73,22 +78,37 @@ class VirtualOrestesApp {
|
|
|
73
78
|
response.headers.forEach((value, key) => {
|
|
74
79
|
originHeaders.push({ name: `x-origin-${key}`, value: value });
|
|
75
80
|
});
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
customHeaders.push({
|
|
82
|
+
name: "x-sk-detected-encoding",
|
|
83
|
+
value: responseEncoding,
|
|
84
|
+
});
|
|
85
|
+
const baqendResponse = new baqend_response_1.BaqendResponse(skResponse.body, response.headers.get("Content-Type"), [...customHeaders, ...originHeaders]);
|
|
80
86
|
this.cache.addEntry(event.request.url, baqendResponse);
|
|
81
87
|
return baqendResponse;
|
|
82
88
|
}
|
|
83
89
|
async getResponseText(response) {
|
|
90
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
84
91
|
const contentType = response.headers.get("content-type") || "";
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
+
const charsetRegex = /charset=([^\s"(),./:;<=>?@[\]]*)/i;
|
|
93
|
+
const encodingFromHeader = contentType && charsetRegex.test(contentType)
|
|
94
|
+
? charsetRegex.exec(contentType)[1]
|
|
95
|
+
: null;
|
|
96
|
+
const encodingFromBuffer = encoding_japanese_1.default.detect(buffer);
|
|
97
|
+
const encodedBody = iconv_lite_2.default
|
|
98
|
+
.decode(buffer, encodingFromHeader ?? encodingFromBuffer)
|
|
99
|
+
.toString();
|
|
100
|
+
const metaSelector = /<meta http-equiv="content-type" content="text\/html;charset=([^\s"(),./:;<=>?@[\]]*)">/is;
|
|
101
|
+
const encodingFromBodyMeta = metaSelector.test(encodedBody)
|
|
102
|
+
? metaSelector.exec(encodedBody)[1]
|
|
103
|
+
: "";
|
|
104
|
+
const detectedEncoding = encodingFromHeader ||
|
|
105
|
+
encodingFromBodyMeta ||
|
|
106
|
+
encodingFromBuffer ||
|
|
107
|
+
"utf-8";
|
|
108
|
+
return {
|
|
109
|
+
responseContent: iconv_lite_1.default.decode(Buffer.from(buffer), detectedEncoding),
|
|
110
|
+
responseEncoding: detectedEncoding,
|
|
111
|
+
};
|
|
92
112
|
}
|
|
93
113
|
returnErrorResponse(customResponse, customHeaders) {
|
|
94
114
|
const message = `Could not transform html: - ${customResponse.error}`;
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@speedkit/cli",
|
|
3
3
|
"description": "Speed Kit CLI",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.6.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Baqend.com",
|
|
7
7
|
"email": "info@baqend.com"
|
|
@@ -81,12 +81,15 @@
|
|
|
81
81
|
"dom-serializer": "2.0.0",
|
|
82
82
|
"domhandler": "5.0.3",
|
|
83
83
|
"domutils": "^3.1",
|
|
84
|
-
"fluent-ffmpeg": "^2.1.3",
|
|
85
84
|
"dotenv": "^16.4.7",
|
|
85
|
+
"encoding-japanese": "^2.2.0",
|
|
86
|
+
"esbuild": "^0.20.2",
|
|
86
87
|
"extract-zip": "^2.0.1",
|
|
88
|
+
"fluent-ffmpeg": "^2.1.3",
|
|
87
89
|
"fs-extra": "^11.2.0",
|
|
88
90
|
"handlebars": "^4.7.8",
|
|
89
91
|
"htmlparser2": "8.0.2",
|
|
92
|
+
"iconv-lite": "^0.6.3",
|
|
90
93
|
"json2csv": "^6.0.0-alpha.2",
|
|
91
94
|
"node-fetch": "^2.7.0",
|
|
92
95
|
"parse5": "7.1",
|
|
@@ -95,10 +98,8 @@
|
|
|
95
98
|
"puppeteer-extra": "^3.3.6",
|
|
96
99
|
"semver": "^7.6.3",
|
|
97
100
|
"strip-comments": "^2.0.1",
|
|
98
|
-
"uuid": "^9.0.1",
|
|
99
|
-
"esbuild": "^0.20.2",
|
|
100
101
|
"ts-node": "^10.9.2",
|
|
101
|
-
"
|
|
102
|
+
"uuid": "^9.0.1"
|
|
102
103
|
},
|
|
103
104
|
"devDependencies": {
|
|
104
105
|
"@commitlint/cli": "^17.8.1",
|