const http = require('http');
const fs = require('fs');
const path = require('path');
// Create an HTTP server
const server = http.createServer((req, res) => {
const parsedUrl = new URL(req.url, 'http://localhost');
const pathname = parsedUrl.pathname;
// Handle different paths
if (pathname === '/') {
// Send a regular response
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(`
<!DOCTYPE html>
<html>
<head><title>Streaming Examples</title></head>
<body>
<h1>Streaming Examples</h1>
<ul>
<li><a href="/stream-text">Stream a large text response</a></li>
<li><a href="/stream-file">Stream a file</a></li>
<li><a href="/stream-json">Stream a JSON response</a></li>
</ul>
</body>
</html>
`);
}
else if (pathname === '/stream-text') {
// Stream a large text response
res.writeHead(200, {'Content-Type': 'text/plain'});
let count = 1;
const max = 10;
// Write response in chunks with delay
const interval = setInterval(() => {
res.write(`Chunk ${count} of data\n`.repeat(20));
if (count >= max) {
clearInterval(interval);
res.end('\nStreaming complete!');
console.log('Text streaming complete');
}
count++;
}, 200);
// Handle client disconnect
req.on('close', () => {
clearInterval(interval);
console.log('Client closed connection during text streaming');
});
}
else if (pathname === '/stream-file') {
// Create a sample file if it doesn't exist
const filePath = path.join(__dirname, 'sample-large-file.txt');
// Create file if it doesn't exist
if (!fs.existsSync(filePath)) {
console.log('Creating sample file...');
const writeStream = fs.createWriteStream(filePath);
for (let i = 0; i < 1000; i++) {
writeStream.write(`Line ${i}: This is a sample line of text for streaming demonstration.\n`);
}
writeStream.end();
console.log('Sample file created');
}
// Get file stats
const stat = fs.statSync(filePath);
// Set headers
res.writeHead(200, {
'Content-Type': 'text/plain',
'Content-Length': stat.size
});
console.log(`Starting file stream (${stat.size} bytes)`);
// Create read stream and pipe to response
const fileStream = fs.createReadStream(filePath);
fileStream.pipe(res);
// Handle file stream events
fileStream.on('open', () => {
console.log('File stream started');
});
fileStream.on('end', () => {
console.log('File stream completed');
});
fileStream.on('error', (err) => {
console.error('File stream error:', err);
if (!res.headersSent) {
res.writeHead(500, {'Content-Type': 'text/plain'});
res.end('Error streaming file');
}
});
// Handle client disconnect
req.on('close', () => {
fileStream.destroy();
console.log('Client closed connection during file streaming');
});
}
else if (pathname === '/stream-json') {
// Stream a large JSON response
res.writeHead(200, {'Content-Type': 'application/json'});
// Start JSON array
res.write('[\n');
let count = 0;
const max = 100;
let isFirst = true;
console.log('Starting JSON streaming...');
// Write JSON objects with delay
const interval = setInterval(() => {
// Add comma for all but first item
if (!isFirst) {
res.write(',\n');
} else {
isFirst = false;
}
// Create a JSON object
const obj = {
id: count,
name: `Item ${count}`,
timestamp: new Date().toISOString(),
data: `Sample data for item ${count}`,
value: Math.random() * 1000
};
// Write the object as JSON (without formatting to save space)
res.write(JSON.stringify(obj));
if (count >= max) {
clearInterval(interval);
// End JSON array
res.write('\n]');
res.end();
console.log('JSON streaming complete');
}
count++;
}, 50);
// Handle client disconnect
req.on('close', () => {
clearInterval(interval);
console.log('Client closed connection during JSON streaming');
});
}
else {
// Handle unknown paths
res.writeHead(404, {'Content-Type': 'text/plain'});
res.end('Not Found');
}
});
// Start the server
const PORT = 3004;
server.listen(PORT, () => {
console.log(`Streaming server running at http://localhost:${PORT}/`);
// Make a test request to the streaming endpoint
console.log('\nTesting text streaming endpoint...');
http.get(`http://localhost:${PORT}/stream-text`, (response) => {
console.log(`Response status: ${response.statusCode} ${response.statusMessage}`);
let data = '';
response.on('data', (chunk) => {
// Just show the first 100 chars of the response
if (data.length < 100) {
data += chunk.toString();
}
});
response.on('end', () => {
console.log('First 100 chars of response:');
console.log(data.substring(0, 100) + '...');
console.log('\nTest file streaming by visiting:');
console.log(`http://localhost:${PORT}/stream-file`);
console.log('\nTest JSON streaming by visiting:');
console.log(`http://localhost:${PORT}/stream-json`);
});
}).on('error', (err) => {
console.error('Error testing streaming endpoint:', err);
});
});
// Handle server errors
server.on('error', (err) => {
console.error('Server error:', err);
});
// Handle process termination
process.on('SIGINT', () => {
console.log('\nShutting down streaming server...');
// Clean up sample file if it exists
const filePath = path.join(__dirname, 'sample-large-file.txt');
if (fs.existsSync(filePath)) {
fs.unlink(filePath, (err) => {
if (err) {
console.error('Error removing sample file:', err);
} else {
console.log('Sample file removed');
}
process.exit(0);
});
} else {
process.exit(0);
}
});