← back to Dw Cowtan Recrawl
probe4.js
32 lines
#!/usr/bin/env node
// Sniff the cowtan SPA shell + JS bundles for the new API endpoints (feed-first discovery).
const https = require('https');
function get(u, m = 5) {
return new Promise((res, rej) => { https.get(u, { timeout: 25000, headers: { 'User-Agent': 'Mozilla/5.0', 'Accept': '*/*' } }, r => {
if ((r.statusCode == 301 || r.statusCode == 302) && r.headers.location && m > 0) { r.resume(); const loc = r.headers.location.startsWith('http') ? r.headers.location : 'https://designs.cowtan.com' + r.headers.location; return get(loc, m - 1).then(res).catch(rej); }
let d = ''; r.on('data', c => d += c); r.on('end', () => res({ status: r.statusCode, body: d })); }).on('error', rej).on('timeout', function () { this.destroy(); rej(new Error('timeout')); }); });
}
(async () => {
const shell = await get('https://designs.cowtan.com/');
console.log('shell', shell.status, 'len', shell.body.length);
// script srcs
const scripts = [...new Set([...shell.body.matchAll(/<script[^>]+src="([^"]+)"/g)].map(m => m[1]))];
console.log('scripts:', scripts.length); scripts.forEach(s => console.log(' ', s));
// inline api hints in shell
const apiHints = [...new Set([...shell.body.matchAll(/["'`](\/(?:api|Search|Design|Product|Catalog)[^"'`\s]*)["'`]/gi)].map(m => m[1]))];
console.log('shell api-path hints:', apiHints.slice(0, 30).join(' '));
// fetch each same-origin/relative JS and grep for fetch/axios/api paths
for (const s of scripts) {
const url = s.startsWith('http') ? s : (s.startsWith('//') ? 'https:' + s : 'https://designs.cowtan.com' + s);
if (!/cowtan/.test(url)) { console.log('skip 3rd-party', url); continue; }
try {
const js = await get(url);
const paths = [...new Set([...js.body.matchAll(/["'`](\/(?:api|Search|Design|Product|Catalog|Get|List|Data)[A-Za-z0-9_\/\-?=&.]*)["'`]/g)].map(m => m[1]))];
const fetches = [...new Set([...js.body.matchAll(/(?:fetch|axios\.\w+|\.get|\.post)\(\s*["'`]([^"'`]+)["'`]/g)].map(m => m[1]))];
console.log('\nJS', url, 'len', js.body.length);
console.log(' api-ish paths:', paths.slice(0, 40).join(' ') || '(none)');
console.log(' fetch/axios urls:', fetches.slice(0, 40).join(' ') || '(none)');
} catch (e) { console.log('JS', url, 'ERR', e.message); }
}
})().catch(e => console.error('FATAL', e.message));