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.
Files changed (79) hide show
  1. package/README.md +3 -2
  2. package/dist/analyzer/apply.d.ts +2 -2
  3. package/dist/analyzer/apply.d.ts.map +1 -1
  4. package/dist/analyzer/apply.js +60 -15
  5. package/dist/analyzer/apply.js.map +1 -1
  6. package/dist/analyzer/apply.test.js +143 -9
  7. package/dist/analyzer/apply.test.js.map +1 -1
  8. package/dist/analyzer/index.d.ts +2 -2
  9. package/dist/analyzer/index.d.ts.map +1 -1
  10. package/dist/analyzer/index.js +2 -2
  11. package/dist/analyzer/index.js.map +1 -1
  12. package/dist/analyzer/index.test.js +20 -7
  13. package/dist/analyzer/index.test.js.map +1 -1
  14. package/dist/analyzer/types.d.ts +0 -4
  15. package/dist/analyzer/types.d.ts.map +1 -1
  16. package/dist/analyzer/util.d.ts +0 -1
  17. package/dist/analyzer/util.d.ts.map +1 -1
  18. package/dist/analyzer/util.js +0 -8
  19. package/dist/analyzer/util.js.map +1 -1
  20. package/dist/browser/index.d.ts +1 -1
  21. package/dist/browser/index.d.ts.map +1 -1
  22. package/dist/browser/index.js +174 -5
  23. package/dist/browser/index.js.map +1 -1
  24. package/dist/browser/index.test.js +957 -2
  25. package/dist/browser/index.test.js.map +1 -1
  26. package/dist/browser/types.d.ts +6 -0
  27. package/dist/browser/types.d.ts.map +1 -1
  28. package/dist/browser/utils.d.ts +1 -0
  29. package/dist/browser/utils.d.ts.map +1 -1
  30. package/dist/browser/utils.js +3 -0
  31. package/dist/browser/utils.js.map +1 -1
  32. package/dist/browser/utils.test.js +9 -2
  33. package/dist/browser/utils.test.js.map +1 -1
  34. package/dist/commands/detect.d.ts.map +1 -1
  35. package/dist/commands/detect.js +12 -20
  36. package/dist/commands/detect.js.map +1 -1
  37. package/dist/commands/detect.test.js +31 -10
  38. package/dist/commands/detect.test.js.map +1 -1
  39. package/dist/commands/detect_types.d.ts +4 -2
  40. package/dist/commands/detect_types.d.ts.map +1 -1
  41. package/dist/commands/detect_utils.d.ts +2 -1
  42. package/dist/commands/detect_utils.d.ts.map +1 -1
  43. package/dist/commands/detect_utils.js +70 -54
  44. package/dist/commands/detect_utils.js.map +1 -1
  45. package/dist/commands/detect_utils.test.js +158 -35
  46. package/dist/commands/detect_utils.test.js.map +1 -1
  47. package/dist/commands/version.test.d.ts +2 -0
  48. package/dist/commands/version.test.d.ts.map +1 -0
  49. package/dist/commands/version.test.js +27 -0
  50. package/dist/commands/version.test.js.map +1 -0
  51. package/dist/e2e/cli.e2e.test.js +1 -1
  52. package/dist/e2e/cli.e2e.test.js.map +1 -1
  53. package/dist/logger/types.js +2 -2
  54. package/dist/logger/types.js.map +1 -1
  55. package/dist/signatures/_types.d.ts +2 -0
  56. package/dist/signatures/_types.d.ts.map +1 -1
  57. package/dist/signatures/index.d.ts.map +1 -1
  58. package/dist/signatures/index.js +2 -0
  59. package/dist/signatures/index.js.map +1 -1
  60. package/dist/signatures/nginx.d.ts.map +1 -1
  61. package/dist/signatures/nginx.js +7 -7
  62. package/dist/signatures/nginx.js.map +1 -1
  63. package/dist/signatures/signatures.test.js +10 -0
  64. package/dist/signatures/signatures.test.js.map +1 -1
  65. package/dist/signatures/technologies/cloudflare.d.ts +3 -0
  66. package/dist/signatures/technologies/cloudflare.d.ts.map +1 -0
  67. package/dist/signatures/technologies/cloudflare.js +20 -0
  68. package/dist/signatures/technologies/cloudflare.js.map +1 -0
  69. package/dist/signatures/technologies/nginx.d.ts.map +1 -1
  70. package/dist/signatures/technologies/nginx.js +1 -0
  71. package/dist/signatures/technologies/nginx.js.map +1 -1
  72. package/dist/signatures/technologies/wordpress.d.ts.map +1 -1
  73. package/dist/signatures/technologies/wordpress.js +1 -0
  74. package/dist/signatures/technologies/wordpress.js.map +1 -1
  75. package/package.json +1 -1
  76. package/dist/signatures/nextjs.d.ts +0 -3
  77. package/dist/signatures/nextjs.d.ts.map +0 -1
  78. package/dist/signatures/nextjs.js +0 -16
  79. package/dist/signatures/nextjs.js.map +0 -1
@@ -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
- export async function openPage(url, timeoutMs, javascriptVariableNames) {
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: ${responseUrl} - ${response.status()}`);
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: response.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
- logger.error(`Error loading page ${url}: ${result.split("\n")[0]}`);
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":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"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"}