debug-time-machine-cli
Version:
π Debug Time Machine CLI - μμ μλνλ React λλ²κΉ λꡬ
320 lines (278 loc) β’ 11.1 kB
JavaScript
/**
* Debug Time Machine Auto-Injector - μμ λ λ²μ
*
* ERR_CONTENT_DECODING_FAILED μλ¬λ₯Ό ν΄κ²°νλ μμ ν μμ λ νλ‘μ μλ²
*/
const http = require('http');
const fs = require('fs');
const path = require('path');
const { URL } = require('url');
const injectorPort = process.env.INJECTOR_PORT || 3001;
const userAppPort = process.env.USER_APP_PORT || 3000;
console.log('π Debug Time Machine Injector Proxy μμ (μμ λ λ²μ )');
console.log(`π νλ‘μ ν¬νΈ: ${injectorPort}`);
console.log(`π― μ¬μ©μ μ± ν¬νΈ: ${userAppPort}`);
// Auto-injector μ€ν¬λ¦½νΈ λ‘λ
const autoInjectorPath = path.join(__dirname, 'auto-injector.js');
let injectorScript = '';
if (fs.existsSync(autoInjectorPath)) {
injectorScript = fs.readFileSync(autoInjectorPath, 'utf8');
console.log('β
Auto-Injector μ€ν¬λ¦½νΈ λ‘λλ¨');
console.log(`π μ€ν¬λ¦½νΈ ν¬κΈ°: ${injectorScript.length} bytes`);
} else {
console.error('β Auto-Injector μ€ν¬λ¦½νΈλ₯Ό μ°Ύμ μ μμ΅λλ€:', autoInjectorPath);
console.error('π νμ¬ λλ ν 리:', __dirname);
console.error('π λλ ν 리 λ΄μ©:', fs.readdirSync(__dirname));
process.exit(1);
}
// νλ‘μ μλ² μμ±
const server = http.createServer((req, res) => {
console.log(`π‘ μμ²: ${req.method} ${req.url}`);
// μ¬μ©μ μ±μΌλ‘ νλ‘μ μμ² μμ±
const proxyOptions = {
hostname: 'localhost',
port: userAppPort,
path: req.url,
method: req.method,
headers: {
...req.headers,
host: `localhost:${userAppPort}`, // μ¬λ°λ₯Έ host ν€λ μ€μ
// μμΆ κ΄λ ¨ ν€λ μ κ±° (λ¬Έμ λ°©μ§)
'accept-encoding': 'identity', // gzip λμ identity μ¬μ©
}
};
// μμΆ κ΄λ ¨ ν€λ μμ μ κ±°
delete proxyOptions.headers['accept-encoding'];
delete proxyOptions.headers['content-encoding'];
const proxyReq = http.request(proxyOptions, (proxyRes) => {
console.log(`π₯ μλ΅: ${proxyRes.statusCode} ${proxyRes.headers['content-type'] || 'unknown'} ${proxyRes.headers['content-encoding'] || 'no-encoding'}`);
const contentType = proxyRes.headers['content-type'] || '';
const isHtml = contentType.toLowerCase().includes('text/html');
const contentEncoding = proxyRes.headers['content-encoding'];
// μμΆλ μλ΅μ μ λ μ²λ¦¬νμ§ μκ³ λ°λ‘ μ λ¬
if (contentEncoding && contentEncoding !== 'identity') {
console.log('π¦ μμΆλ μλ΅ κ°μ§ - μ€νΈλ¦ΌμΌλ‘ μ§μ μ λ¬');
// ν€λ κ·Έλλ‘ λ³΅μ¬ν΄μ μ λ¬
res.writeHead(proxyRes.statusCode, proxyRes.headers);
// μ€νΈλ¦ΌμΌλ‘ μ§μ νμ΄ν
proxyRes.pipe(res);
return;
}
// HTMLμ΄ μλ κ²½μ°μλ μ€νΈλ¦ΌμΌλ‘ λ°λ‘ μ λ¬
if (!isHtml) {
console.log('π λΉHTML μλ΅ - μ€νΈλ¦ΌμΌλ‘ μ§μ μ λ¬');
// ν€λ κ·Έλλ‘ λ³΅μ¬ν΄μ μ λ¬
res.writeHead(proxyRes.statusCode, proxyRes.headers);
// μ€νΈλ¦ΌμΌλ‘ μ§μ νμ΄ν
proxyRes.pipe(res);
return;
}
// HTML μλ΅λ§ λ²νΌλ§ν΄μ μ²λ¦¬
let body = '';
// μλ΅ λ°μ΄ν° μμ§
proxyRes.on('data', (chunk) => {
body += chunk.toString('utf8'); // λͺ
μμ μΌλ‘ UTF-8 μΈμ½λ© μ¬μ©
});
proxyRes.on('end', () => {
try {
// μλ΅ ν€λ 볡μ¬νλ λ¬Έμ κ° λ μ μλ ν€λλ€ μμ μ κ±°
const responseHeaders = { ...proxyRes.headers };
// μμΆ λ° μΈμ½λ© κ΄λ ¨ ν€λ μμ μ κ±°
delete responseHeaders['content-length'];
delete responseHeaders['content-encoding'];
delete responseHeaders['transfer-encoding'];
delete responseHeaders['content-range'];
delete responseHeaders['accept-ranges'];
// μΊμ λ°©μ§ ν€λ μΆκ° (κ°λ° νκ²½μ©)
responseHeaders['cache-control'] = 'no-cache, no-store, must-revalidate';
responseHeaders['pragma'] = 'no-cache';
responseHeaders['expires'] = '0';
// Content-Type λͺ
μμ μ€μ
responseHeaders['content-type'] = 'text/html; charset=utf-8';
// HTMLμ μ€ν¬λ¦½νΈ μ£Όμ
μλ
if (body && body.toLowerCase().includes('<head')) {
console.log('π― HTML μλ΅ κ°μ§, Auto-Injector μ£Όμ
μ€...');
const injectedBody = body.replace(
/<head[^>]*>/i,
`$&
<!-- Debug Time Machine Auto-Injector (Fixed Version) -->
<script>
console.log('π Debug Time Machine Auto-Injector λ‘λ© (μ¬μ©μ μ± - μμ λ λ²μ )...');
try {
${injectorScript}
} catch (error) {
console.error('β Auto-Injector μ΄κΈ°ν μ€ν¨:', error);
}
</script>
<!-- End Debug Time Machine Auto-Injector -->`
);
if (injectedBody !== body && injectedBody.length > body.length) {
console.log('β
Auto-Injector μ€ν¬λ¦½νΈκ° μ¬μ©μ μ±μ μ£Όμ
λμμ΅λλ€');
console.log(`π μλ³Έ ν¬κΈ°: ${body.length} bytes β μ£Όμ
ν: ${injectedBody.length} bytes`);
// μμ λ content-length μ€μ
const finalBody = injectedBody;
responseHeaders['content-length'] = Buffer.byteLength(finalBody, 'utf8').toString();
res.writeHead(proxyRes.statusCode, responseHeaders);
res.end(finalBody);
} else {
console.log('β οΈ μ€ν¬λ¦½νΈ μ£Όμ
μ€ν¨ - μλ³Έ μλ΅ μ λ¬');
console.log('π μλ΅ μμ λΆλΆ:', body.substring(0, 200));
responseHeaders['content-length'] = Buffer.byteLength(body, 'utf8').toString();
res.writeHead(proxyRes.statusCode, responseHeaders);
res.end(body);
}
} else {
// <head> νκ·Έκ° μλ HTML
console.log('β οΈ <head> νκ·Έκ° μλ HTML μλ΅ - μλ³Έ μ λ¬');
responseHeaders['content-length'] = Buffer.byteLength(body, 'utf8').toString();
res.writeHead(proxyRes.statusCode, responseHeaders);
res.end(body);
}
} catch (error) {
console.error('β μλ΅ μ²λ¦¬ μ€ μ€λ₯:', error);
// μ€λ₯ λ°μ μ μλ³Έ μλ΅ κ·Έλλ‘ μ λ¬
const safeHeaders = { ...proxyRes.headers };
delete safeHeaders['content-encoding'];
res.writeHead(proxyRes.statusCode, safeHeaders);
res.end(body);
}
});
});
// νλ‘μ μμ² μλ¬ μ²λ¦¬
proxyReq.on('error', (error) => {
console.error('β νλ‘μ μμ² μλ¬:', error.message);
if (!res.headersSent) {
res.writeHead(500, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(`
<!DOCTYPE html>
<html>
<head>
<title>Debug Time Machine - νλ‘μ μλ¬</title>
<meta charset="utf-8">
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
text-align: center;
padding: 2rem;
background: #f5f5f5;
margin: 0;
}
.container {
max-width: 600px;
margin: 0 auto;
background: white;
padding: 2rem;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.error {
color: #e74c3c;
background: #fee;
padding: 1rem;
border-radius: 5px;
margin: 1rem 0;
border: 1px solid #fcc;
}
.info {
color: #3498db;
background: #eff8ff;
padding: 1rem;
border-radius: 5px;
margin: 1rem 0;
border: 1px solid #bde4ff;
}
code {
background: #f8f9fa;
padding: 2px 6px;
border-radius: 3px;
font-family: 'Monaco', 'Menlo', monospace;
}
</style>
</head>
<body>
<div class="container">
<h1>π°οΈ Debug Time Machine</h1>
<div class="error">
<h3>νλ‘μ μ°κ²° μλ¬</h3>
<p>μ¬μ©μ μ±(ν¬νΈ ${userAppPort})μ μ°κ²°ν μ μμ΅λλ€.</p>
<p><strong>μλ¬:</strong> ${error.message}</p>
</div>
<div class="info">
<h3>π§ ν΄κ²° λ°©λ²</h3>
<p>1. μ¬μ©μ μ±μ΄ <code>http://localhost:${userAppPort}</code>μμ μ€ν μ€μΈμ§ νμΈνμΈμ</p>
<p>2. ν°λ―Έλμμ λ€μ λͺ
λ Ήμ΄λ‘ νμΈ: <code>curl http://localhost:${userAppPort}</code></p>
<p>3. μ¬μ©μ μ±μ λ€μ μμν΄λ³΄μΈμ</p>
<p>4. ν¬νΈ ${userAppPort}κ° λ€λ₯Έ μ±μμ μ¬μ© μ€μΈμ§ νμΈνμΈμ</p>
</div>
</div>
</body>
</html>
`);
}
});
// μμ² λ°μ΄ν° μ λ¬
req.on('data', (chunk) => {
proxyReq.write(chunk);
});
req.on('end', () => {
proxyReq.end();
});
// ν΄λΌμ΄μΈνΈ μμ² μλ¬ μ²λ¦¬
req.on('error', (error) => {
console.error('β ν΄λΌμ΄μΈνΈ μμ² μλ¬:', error.message);
proxyReq.destroy();
});
});
// μλ² μμ
server.listen(injectorPort, () => {
console.log('π Debug Time Machine Injector Proxy μμλ¨! (μμ λ λ²μ )');
console.log(`π νλ‘μ URL: http://localhost:${injectorPort}`);
console.log(`π― μ¬μ©μ μ± URL: http://localhost:${userAppPort}`);
console.log('');
console.log('π‘ μ¬μ©λ²:');
console.log(` λΈλΌμ°μ μμ http://localhost:${injectorPort} λ₯Ό μ΄λ©΄`);
console.log(` μλμΌλ‘ Debug Time Machineμ΄ μ£Όμ
λ μ¬μ©μ μ±μ λ³Ό μ μμ΅λλ€.`);
console.log('');
console.log('π§ μμ μ¬ν:');
console.log(' - μμΆ ν€λ μμ μ κ±°');
console.log(' - UTF-8 μΈμ½λ© λͺ
μ');
console.log(' - μλ¬ μ²λ¦¬ κ°ν');
console.log(' - ν€λ μΆ©λ λ°©μ§');
console.log('');
// μ°κ²° ν
μ€νΈ
setTimeout(() => {
console.log('π μ¬μ©μ μ± μ°κ²° ν
μ€νΈ...');
const testReq = http.get(`http://localhost:${userAppPort}`, (testRes) => {
console.log(`β
μ¬μ©μ μ± μ°κ²° νμΈλ¨ (μν: ${testRes.statusCode})`);
}).on('error', (error) => {
console.log(`β οΈ μ¬μ©μ μ± μ°κ²° μ€ν¨: ${error.message}`);
console.log(' μ¬μ©μ μ±μ΄ μμ§ μμλμ§ μμμ μ μμ΅λλ€.');
});
}, 2000);
});
// μλ¬ μ²λ¦¬
server.on('error', (error) => {
if (error.code === 'EADDRINUSE') {
console.error(`β ν¬νΈ ${injectorPort}κ° μ΄λ―Έ μ¬μ© μ€μ
λλ€.`);
console.error(' λ€λ₯Έ ν¬νΈλ₯Ό μ¬μ©νκ±°λ κΈ°μ‘΄ νλ‘μΈμ€λ₯Ό μ’
λ£νμΈμ.');
} else {
console.error('β μλ² μμ μλ¬:', error);
}
process.exit(1);
});
// μ’
λ£ μ²λ¦¬
process.on('SIGINT', () => {
console.log('\nπ§Ή Debug Time Machine Injector Proxy μ’
λ£ μ€...');
server.close(() => {
console.log('β
μλ²κ° μ μμ μΌλ‘ μ’
λ£λμμ΅λλ€.');
process.exit(0);
});
});
process.on('SIGTERM', () => {
console.log('\nπ§Ή Debug Time Machine Injector Proxy μ’
λ£ μ€...');
server.close(() => {
console.log('β
μλ²κ° μ μμ μΌλ‘ μ’
λ£λμμ΅λλ€.');
process.exit(0);
});
});