whopper 0.1.9 → 0.3.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/README.md +3 -2
- package/dist/analyzer/apply.d.ts +2 -2
- package/dist/analyzer/apply.d.ts.map +1 -1
- package/dist/analyzer/apply.js +60 -15
- package/dist/analyzer/apply.js.map +1 -1
- package/dist/analyzer/apply.test.js +143 -9
- package/dist/analyzer/apply.test.js.map +1 -1
- package/dist/analyzer/index.d.ts +2 -2
- package/dist/analyzer/index.d.ts.map +1 -1
- package/dist/analyzer/index.js +2 -2
- package/dist/analyzer/index.js.map +1 -1
- package/dist/analyzer/index.test.js +20 -7
- package/dist/analyzer/index.test.js.map +1 -1
- package/dist/analyzer/types.d.ts +0 -4
- package/dist/analyzer/types.d.ts.map +1 -1
- package/dist/analyzer/util.d.ts +0 -1
- package/dist/analyzer/util.d.ts.map +1 -1
- package/dist/analyzer/util.js +0 -8
- package/dist/analyzer/util.js.map +1 -1
- package/dist/browser/index.d.ts +1 -1
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.js +174 -5
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.test.js +957 -2
- package/dist/browser/index.test.js.map +1 -1
- package/dist/browser/types.d.ts +6 -0
- package/dist/browser/types.d.ts.map +1 -1
- package/dist/browser/utils.d.ts +1 -0
- package/dist/browser/utils.d.ts.map +1 -1
- package/dist/browser/utils.js +3 -0
- package/dist/browser/utils.js.map +1 -1
- package/dist/browser/utils.test.js +9 -2
- package/dist/browser/utils.test.js.map +1 -1
- package/dist/commands/detect.d.ts.map +1 -1
- package/dist/commands/detect.js +12 -20
- package/dist/commands/detect.js.map +1 -1
- package/dist/commands/detect.test.js +31 -10
- package/dist/commands/detect.test.js.map +1 -1
- package/dist/commands/detect_types.d.ts +4 -2
- package/dist/commands/detect_types.d.ts.map +1 -1
- package/dist/commands/detect_utils.d.ts +2 -1
- package/dist/commands/detect_utils.d.ts.map +1 -1
- package/dist/commands/detect_utils.js +70 -54
- package/dist/commands/detect_utils.js.map +1 -1
- package/dist/commands/detect_utils.test.js +158 -35
- package/dist/commands/detect_utils.test.js.map +1 -1
- package/dist/commands/version.test.d.ts +2 -0
- package/dist/commands/version.test.d.ts.map +1 -0
- package/dist/commands/version.test.js +27 -0
- package/dist/commands/version.test.js.map +1 -0
- package/dist/e2e/cli.e2e.test.js +1 -1
- package/dist/e2e/cli.e2e.test.js.map +1 -1
- package/dist/logger/types.js +2 -2
- package/dist/logger/types.js.map +1 -1
- package/dist/signatures/_types.d.ts +2 -0
- package/dist/signatures/_types.d.ts.map +1 -1
- package/dist/signatures/index.d.ts.map +1 -1
- package/dist/signatures/index.js +2 -0
- package/dist/signatures/index.js.map +1 -1
- package/dist/signatures/nginx.d.ts.map +1 -1
- package/dist/signatures/nginx.js +7 -7
- package/dist/signatures/nginx.js.map +1 -1
- package/dist/signatures/signatures.test.js +10 -0
- package/dist/signatures/signatures.test.js.map +1 -1
- package/dist/signatures/technologies/cloudflare.d.ts +3 -0
- package/dist/signatures/technologies/cloudflare.d.ts.map +1 -0
- package/dist/signatures/technologies/cloudflare.js +20 -0
- package/dist/signatures/technologies/cloudflare.js.map +1 -0
- package/dist/signatures/technologies/nginx.d.ts.map +1 -1
- package/dist/signatures/technologies/nginx.js +1 -0
- package/dist/signatures/technologies/nginx.js.map +1 -1
- package/dist/signatures/technologies/wordpress.d.ts.map +1 -1
- package/dist/signatures/technologies/wordpress.js +1 -0
- package/dist/signatures/technologies/wordpress.js.map +1 -1
- package/package.json +1 -1
- package/dist/signatures/nextjs.d.ts +0 -3
- package/dist/signatures/nextjs.d.ts.map +0 -1
- package/dist/signatures/nextjs.js +0 -16
- package/dist/signatures/nextjs.js.map +0 -1
package/dist/browser/index.js
CHANGED
|
@@ -1,7 +1,28 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
1
2
|
import { chromium } from "playwright";
|
|
2
|
-
import { sleep, extractJsVariables, getHostFromUrl, isFirstPartyHost, } from "./utils.js";
|
|
3
3
|
import { logger } from "../logger/index.js";
|
|
4
|
-
|
|
4
|
+
import { extractJsVariables, getHostFromUrl, isFirstPartyHost, isSameHost, sleep, } from "./utils.js";
|
|
5
|
+
const MAX_REDIRECT_HOPS = 20;
|
|
6
|
+
function colorizeStatusCode(statusCode) {
|
|
7
|
+
const code = String(statusCode);
|
|
8
|
+
if (statusCode >= 100 && statusCode < 200) {
|
|
9
|
+
return chalk.cyan(code);
|
|
10
|
+
}
|
|
11
|
+
if (statusCode >= 200 && statusCode < 300) {
|
|
12
|
+
return chalk.green(code);
|
|
13
|
+
}
|
|
14
|
+
if (statusCode >= 300 && statusCode < 400) {
|
|
15
|
+
return chalk.blue(code);
|
|
16
|
+
}
|
|
17
|
+
if (statusCode >= 400 && statusCode < 500) {
|
|
18
|
+
return chalk.yellow(code);
|
|
19
|
+
}
|
|
20
|
+
if (statusCode >= 500 && statusCode < 600) {
|
|
21
|
+
return chalk.red(code);
|
|
22
|
+
}
|
|
23
|
+
return chalk.gray(code);
|
|
24
|
+
}
|
|
25
|
+
export async function openPage(url, timeoutMs, javascriptVariableNames, userAgent, blockCrossDomainRedirect = false) {
|
|
5
26
|
const pageHost = getHostFromUrl(url);
|
|
6
27
|
if (!pageHost) {
|
|
7
28
|
throw new Error(`Invalid URL: ${url}`);
|
|
@@ -9,20 +30,156 @@ export async function openPage(url, timeoutMs, javascriptVariableNames) {
|
|
|
9
30
|
const browser = await chromium.launch({ headless: true });
|
|
10
31
|
const context = await browser.newContext({
|
|
11
32
|
ignoreHTTPSErrors: true,
|
|
33
|
+
...(userAgent ? { userAgent } : {}),
|
|
12
34
|
});
|
|
13
35
|
const page = await context.newPage();
|
|
36
|
+
let blockedByRedirectPolicy = false;
|
|
37
|
+
let lastNavigationUrl = url;
|
|
38
|
+
let inspectedUrls = new Set();
|
|
39
|
+
let reentryCount = 0;
|
|
40
|
+
const preInspectedUrls = new Set();
|
|
41
|
+
await page.route("**/*", async (route) => {
|
|
42
|
+
const request = route.request();
|
|
43
|
+
if (!request.isNavigationRequest() ||
|
|
44
|
+
request.frame() !== page.mainFrame()) {
|
|
45
|
+
await route.continue();
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const targetUrl = request.url();
|
|
49
|
+
const targetHost = getHostFromUrl(targetUrl);
|
|
50
|
+
if (!targetHost) {
|
|
51
|
+
await route.continue();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// Skip URLs already inspected by the pre-inspection loop to prevent
|
|
55
|
+
// infinite re-entry: fulfill(301) may cause the browser to re-invoke
|
|
56
|
+
// this handler, and without this guard a circular redirect chain
|
|
57
|
+
// would loop indefinitely outside the MAX_REDIRECT_HOPS limit.
|
|
58
|
+
if (inspectedUrls.has(targetUrl)) {
|
|
59
|
+
reentryCount++;
|
|
60
|
+
if (reentryCount > MAX_REDIRECT_HOPS) {
|
|
61
|
+
logger.warn("Too many redirect re-entries, aborting");
|
|
62
|
+
await route.abort("failed");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
await route.continue();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
if (blockCrossDomainRedirect &&
|
|
69
|
+
!isSameHost(pageHost, targetHost)) {
|
|
70
|
+
logger.warn(`Blocked cross-domain redirect: ${targetUrl}`);
|
|
71
|
+
blockedByRedirectPolicy = true;
|
|
72
|
+
urls.push({ url: targetUrl, error: "Blocked cross-domain redirect" });
|
|
73
|
+
await route.abort("blockedbyclient");
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
// Log client-side redirects (JS / meta refresh)
|
|
77
|
+
if (targetUrl !== lastNavigationUrl) {
|
|
78
|
+
logger.info(`Following redirect: ${lastNavigationUrl} -> ${targetUrl}`);
|
|
79
|
+
}
|
|
80
|
+
lastNavigationUrl = targetUrl;
|
|
81
|
+
// New set per navigation so previous chains don't interfere,
|
|
82
|
+
// but re-entry from the same chain still hits the guard above.
|
|
83
|
+
inspectedUrls = new Set();
|
|
84
|
+
reentryCount = 0;
|
|
85
|
+
// Fetch without following redirects so we can inspect each hop
|
|
86
|
+
let currentUrl = targetUrl;
|
|
87
|
+
let response;
|
|
88
|
+
try {
|
|
89
|
+
response = await route.fetch({ maxRedirects: 0 });
|
|
90
|
+
}
|
|
91
|
+
catch (e) {
|
|
92
|
+
const message = (e instanceof Error ? e.message : String(e)).split("\n")[0] ?? "";
|
|
93
|
+
urls.push({ url: targetUrl, error: message });
|
|
94
|
+
await route.abort("failed");
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
// Pre-inspect the 3xx chain to log each hop and enforce the redirect
|
|
98
|
+
// policy before the browser sees any response. After inspection we
|
|
99
|
+
// fulfill with the *first* response so the browser follows the real
|
|
100
|
+
// chain itself, preserving Set-Cookie headers, origin, and URL state.
|
|
101
|
+
// URLs captured here are added to preInspectedUrls so that the
|
|
102
|
+
// page.on("response") listener can skip them and avoid duplicates.
|
|
103
|
+
const firstResponse = response;
|
|
104
|
+
for (let hop = 0; hop < MAX_REDIRECT_HOPS && response.status() >= 300 && response.status() < 400; hop++) {
|
|
105
|
+
// Capture intermediate 3xx responses so their headers (e.g. server,
|
|
106
|
+
// x-powered-by) are available for analysis even though the browser
|
|
107
|
+
// never sees these responses directly.
|
|
108
|
+
const hopHost = getHostFromUrl(currentUrl) ?? "";
|
|
109
|
+
preInspectedUrls.add(currentUrl);
|
|
110
|
+
const hopBody = await response.text().catch(() => null);
|
|
111
|
+
const hopResponse = {
|
|
112
|
+
url: currentUrl,
|
|
113
|
+
host: hopHost,
|
|
114
|
+
isFirstParty: hopHost ? isFirstPartyHost(pageHost, hopHost) : false,
|
|
115
|
+
status: response.status(),
|
|
116
|
+
headers: response.headers(),
|
|
117
|
+
};
|
|
118
|
+
if (hopBody) {
|
|
119
|
+
hopResponse.body = hopBody;
|
|
120
|
+
}
|
|
121
|
+
responses.push(hopResponse);
|
|
122
|
+
urls.push({ url: currentUrl, status: response.status() });
|
|
123
|
+
const location = response.headers()["location"];
|
|
124
|
+
if (!location)
|
|
125
|
+
break;
|
|
126
|
+
let redirectUrl;
|
|
127
|
+
try {
|
|
128
|
+
redirectUrl = new URL(location, currentUrl).href;
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
const redirectHost = getHostFromUrl(redirectUrl);
|
|
134
|
+
if (blockCrossDomainRedirect &&
|
|
135
|
+
redirectHost &&
|
|
136
|
+
!isSameHost(pageHost, redirectHost)) {
|
|
137
|
+
logger.warn(`Blocked cross-domain redirect: ${redirectUrl}`);
|
|
138
|
+
blockedByRedirectPolicy = true;
|
|
139
|
+
urls.push({ url: redirectUrl, error: "Blocked cross-domain redirect" });
|
|
140
|
+
await route.abort("blockedbyclient");
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
logger.info(`Following redirect: ${currentUrl} -> ${redirectUrl}`);
|
|
144
|
+
lastNavigationUrl = redirectUrl;
|
|
145
|
+
currentUrl = redirectUrl;
|
|
146
|
+
inspectedUrls.add(redirectUrl);
|
|
147
|
+
try {
|
|
148
|
+
response = await route.fetch({ url: redirectUrl, maxRedirects: 0 });
|
|
149
|
+
}
|
|
150
|
+
catch (e) {
|
|
151
|
+
const message = (e instanceof Error ? e.message : String(e)).split("\n")[0] ?? "";
|
|
152
|
+
urls.push({ url: redirectUrl, error: message });
|
|
153
|
+
await route.abort("failed");
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
await route.fulfill({ response: firstResponse });
|
|
158
|
+
});
|
|
159
|
+
const urls = [];
|
|
14
160
|
const responses = [];
|
|
15
161
|
page.on("response", async (response) => {
|
|
16
162
|
const responseUrl = response.url();
|
|
163
|
+
const statusCode = response.status();
|
|
164
|
+
// Skip responses already captured by the pre-inspection loop to
|
|
165
|
+
// avoid duplicates.
|
|
166
|
+
if (preInspectedUrls.has(responseUrl) && statusCode >= 300 && statusCode < 400) {
|
|
167
|
+
logger.debug(`Skipping already captured response [${colorizeStatusCode(statusCode)}] ${responseUrl}`);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
17
170
|
const responseHost = getHostFromUrl(responseUrl) ?? "";
|
|
18
|
-
logger.debug(`Received response
|
|
171
|
+
logger.debug(`Received response [${colorizeStatusCode(statusCode)}] ${responseUrl}`);
|
|
172
|
+
const request = response.request();
|
|
173
|
+
if (request.isNavigationRequest() && request.frame() === page.mainFrame()) {
|
|
174
|
+
urls.push({ url: responseUrl, status: statusCode });
|
|
175
|
+
}
|
|
19
176
|
const res = {
|
|
20
177
|
url: responseUrl,
|
|
21
178
|
host: responseHost,
|
|
22
179
|
isFirstParty: responseHost
|
|
23
180
|
? isFirstPartyHost(pageHost, responseHost)
|
|
24
181
|
: false,
|
|
25
|
-
status:
|
|
182
|
+
status: statusCode,
|
|
26
183
|
headers: response.headers(),
|
|
27
184
|
};
|
|
28
185
|
const body = await response.text().catch(() => null);
|
|
@@ -44,8 +201,19 @@ export async function openPage(url, timeoutMs, javascriptVariableNames) {
|
|
|
44
201
|
timeoutOccurred = true;
|
|
45
202
|
logger.warn(`Timeout of ${timeoutMs}ms exceeded while loading ${url}`);
|
|
46
203
|
}
|
|
204
|
+
else if (blockedByRedirectPolicy) {
|
|
205
|
+
// Already logged by the route handler as "Blocked redirect by policy"
|
|
206
|
+
}
|
|
47
207
|
else {
|
|
48
|
-
|
|
208
|
+
const errorMessage = `Error loading page ${url}: ${result.split("\n")[0]}`;
|
|
209
|
+
logger.error(errorMessage);
|
|
210
|
+
// Fallback: record the error only when the route handler never ran
|
|
211
|
+
// (e.g. DNS failure on the initial URL). If the route handler already
|
|
212
|
+
// captured entries (e.g. a 302 hop followed by a fetch error), the
|
|
213
|
+
// error is already in urls via the route.fetch catch block.
|
|
214
|
+
if (urls.length === 0) {
|
|
215
|
+
urls.push({ url, error: errorMessage });
|
|
216
|
+
}
|
|
49
217
|
}
|
|
50
218
|
let cookies = [];
|
|
51
219
|
let javascriptVariables = {};
|
|
@@ -80,6 +248,7 @@ export async function openPage(url, timeoutMs, javascriptVariableNames) {
|
|
|
80
248
|
return {
|
|
81
249
|
browser,
|
|
82
250
|
page,
|
|
251
|
+
urls,
|
|
83
252
|
responses,
|
|
84
253
|
javascriptVariables,
|
|
85
254
|
cookies,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"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"}
|