HTTP/2 কি?
Node.js HTTP/2 HTTP/2 , , , .
HTTP/2 বিভিন্ন গুরুত্বপূর্ণ বৈশিষ্ট্য সহ HTTP/1.1 এ উন্নতি করে:
বাইনারি প্রোটোকল
HTTP/2 ডেটা স্থানান্তরের জন্য পাঠ্য বিন্যাসের পরিবর্তে একটি বাইনারি বিন্যাস ব্যবহার করে, এটি পার্সিংয়ের জন্য আরও দক্ষ করে তোলে।
মাল্টিপ্লেক্সিং
একাধিক অনুরোধ এবং প্রতিক্রিয়া একযোগে একযোগে পাঠানো যেতে পারে
হেডার কম্প্রেশন
HTTP/2 ওভারহেড কমাতে হেডার কম্প্রেস করে
সার্ভার পুশ
ক্লায়েন্টদের অনুরোধ করার আগে সার্ভার সক্রিয়ভাবে সম্পদ পাঠাতে পারে
স্ট্রিম অগ্রাধিকার
বিভিন্ন অগ্রাধিকার দিয়ে সম্পদ বরাদ্দ করা যেতে পারে
HTTP/2 প্যাকেজ ব্যবহার করে
Node.js , HTTP/2 :
const http2 = require('http2');
HTTP/2 মডিউলটি Node.js v10.0.0 থেকে স্থিতিশীল। মনে রাখবেন যে HTTP/2 এর জন্য বেশিরভাগ ব্রাউজারে একটি নিরাপদ সংযোগ (HTTPS) প্রয়োজন, তাই বেশিরভাগ উদাহরণ TLS/SSL ব্যবহার করবে।
একটি HTTP/2 সার্ভার তৈরি করা হচ্ছে
এখানে TLS ব্যবহার করে একটি মৌলিক HTTP/2 সার্ভার তৈরি করার একটি উদাহরণ রয়েছে:
const http2 = require('http2');
const fs = require('fs');
const path = require('path');
// Read the TLS certificate and key
const options = {
key: fs.readFileSync(path.join(__dirname, 'server.key')),
cert: fs.readFileSync(path.join(__dirname, 'server.crt'))
};
// Create an HTTP/2 server
const server = http2.createSecureServer(options);
// Handle stream events
server.on('stream', (stream, headers) => {
// Get the path from headers
const path = headers[':path'];
// Send a response
if (path === '/') {
stream.respond({
'content-type': 'text/html',
':status': 200
});
stream.end('Hello from HTTP/2!
');
} else {
stream.respond({
':status': 404
});
stream.end('Not found');
}
});
// Start the server
const port = 8080;
server.listen(port, () => {
console.log(`HTTP/2 server running at https://localhost:${port}`);
});
দ্রষ্টব্য:
এই উদাহরণটি ধরে নেয় যে আপনার কাছে TLS সার্টিফিকেট ফাইল আছে। উন্নয়নের জন্য, আপনি OpenSSL ব্যবহার করে স্ব-স্বাক্ষরিত শংসাপত্র তৈরি করতে পারেন। উত্পাদনের জন্য, একটি বিশ্বস্ত শংসাপত্র কর্তৃপক্ষ ব্যবহার করুন৷
TLS ছাড়া HTTP/2 সার্ভার
আপনি এনক্রিপশন ছাড়াই সরাসরি HTTP/2 সংযোগের জন্য TLS ছাড়াই একটি HTTP/2 সার্ভার তৈরি করতে পারেন:
const http2 = require('http2');
// Create an HTTP/2 server without TLS
const server = http2.createServer();
server.on('stream', (stream, headers) => {
stream.respond({
'content-type': 'text/html',
':status': 200
});
stream.end('Hello from HTTP/2 without TLS!
');
});
server.listen(8080);
দ্রষ্টব্য:
বেশিরভাগ আধুনিক ব্রাউজার শুধুমাত্র TLS এর উপর HTTP/2 সমর্থন করে, তাই একটি অনিরাপদ HTTP/2 সার্ভার সাধারণত শুধুমাত্র ডেডিকেটেড HTTP/2 ক্লায়েন্টের সাথে কাজ করবে যা স্পষ্টভাবে ক্লিয়ারটেক্সট HTTP/2 সমর্থন করে।
HTTP/2 ক্লায়েন্ট
একটি HTTP/2 সার্ভারের সাথে সংযোগ করতে একটি HTTP/2 ক্লায়েন্ট তৈরি করা:
const http2 = require('http2');
// Create a client
const client = http2.connect('https://localhost:8080', {
// For self-signed certificates in development
rejectUnauthorized: false
});
// Error handling
client.on('error', (err) => {
console.error('Client error:', err);
});
// Create a request
const req = client.request({ ':path': '/' });
// Handle response data
req.on('response', (headers) => {
console.log('Status:', headers[':status']);
console.log('Headers:', headers);
});
req.on('data', (chunk) => {
console.log('Received data:', chunk.toString());
});
req.on('end', () => {
console.log('Request completed');
client.close();
});
// Send the request
req.end();
HTTP/2 স্ট্রীম
HTTP/2 ক্লায়েন্ট এবং সার্ভারের মধ্যে যোগাযোগের জন্য স্ট্রিম ব্যবহার করে। প্রতিটি স্ট্রীম ক্লায়েন্ট এবং সার্ভারের মধ্যে বিনিময় করা স্বাধীন, দ্বি-দিকনির্দেশক ফ্রেমের একটি ক্রম প্রতিনিধিত্ব করে।
স্ট্রিম ইভেন্ট
গুরুত্বপূর্ণ স্ট্রিম ইভেন্ট:
'headers'
হেডার প্রাপ্ত হলে নির্গত হয়
'data'
এক খণ্ড ডেটা প্রাপ্ত হলে নির্গত হয়
'end'
স্ট্রীম সম্পূর্ণ হলে নির্গত হয়
'error'
কোনো ত্রুটি ঘটলে নির্গত হয়
উদাহরণ: স্ট্রিম ইভেন্ট পরিচালনা করা
const http2 = require('http2');
const fs = require('fs');
const path = require('path');
// Create a server
const server = http2.createSecureServer({
key: fs.readFileSync(path.join(__dirname, 'server.key')),
cert: fs.readFileSync(path.join(__dirname, 'server.crt'))
});
server.on('stream', (stream, headers) => {
// Handle stream events
stream.on('error', (error) => {
console.error('Stream error:', error);
});
stream.on('close', () => {
console.log('Stream closed');
});
// Handle request
stream.respond({
'content-type': 'text/plain',
':status': 200
});
// Send data in multiple chunks
stream.write('First chunk of data\n');
setTimeout(() => {
stream.write('Second chunk of data\n');
stream.end('Final chunk of data');
}, 1000);
});
server.listen(8080);
HTTP/2 সার্ভার পুশ
সার্ভার পুশ সার্ভারগুলিকে ক্লায়েন্টদের স্পষ্টভাবে অনুরোধ করার আগে সক্রিয়ভাবে সংস্থানগুলি প্রেরণ করার অনুমতি দেয়। এটি রাউন্ড-ট্রিপ বিলম্ব দূর করে কর্মক্ষমতা উন্নত করে।
const http2 = require('http2');
const fs = require('fs');
const path = require('path');
const options = {
key: fs.readFileSync(path.join(__dirname, 'server.key')),
cert: fs.readFileSync(path.join(__dirname, 'server.crt'))
};
const server = http2.createSecureServer(options);
server.on('stream', (stream, headers) => {
const requestPath = headers[':path'];
if (requestPath === '/') {
// Push CSS and JavaScript resources
stream.pushStream({ ':path': '/style.css' }, (err, pushStream) => {
if (err) {
console.error('Error pushing stream:', err);
return;
}
pushStream.respond({
'content-type': 'text/css',
':status': 200
});
pushStream.end('body { color: blue; }');
});
stream.pushStream({ ':path': '/script.js' }, (err, pushStream) => {
if (err) {
console.error('Error pushing stream:', err);
return;
}
pushStream.respond({
'content-type': 'application/javascript',
':status': 200
});
pushStream.end('console.log("Hello from HTTP/2 server push!");');
});
// Send the main HTML document
stream.respond({
'content-type': 'text/html',
':status': 200
});
stream.end(`
HTTP/2 Server Push Example
HTTP/2 Server Push Demo
CSS and JavaScript were pushed by the server!
`);
} else {
// Serve pushed resources if requested directly
if (requestPath === '/style.css') {
stream.respond({
'content-type': 'text/css',
':status': 200
});
stream.end('body { color: blue; }');
} else if (requestPath === '/script.js') {
stream.respond({
'content-type': 'application/javascript',
':status': 200
});
stream.end('console.log("Hello from HTTP/2 server push!");');
} else {
// Not found
stream.respond({ ':status': 404 });
stream.end('Not found');
}
}
});
server.listen(8080);
HTTP/2 হেডার
HTTP/2 হেডারের জন্য একটি ভিন্ন বিন্যাস ব্যবহার করে। বিশেষ করে, সমস্ত শিরোনাম ছোট হাতের, এবং অনুরোধ ছদ্ম-শিরোনাম একটি কোলন (:) দিয়ে শুরু হয়।
const http2 = require('http2');
// HTTP/2 pseudo-headers
const {
HTTP2_HEADER_METHOD,
HTTP2_HEADER_PATH,
HTTP2_HEADER_AUTHORITY,
HTTP2_HEADER_SCHEME,
HTTP2_HEADER_STATUS
} = http2.constants;
// Create a client
const client = http2.connect('https://localhost:8080', {
rejectUnauthorized: false
});
// Send a request with custom headers
const req = client.request({
[HTTP2_HEADER_METHOD]: 'GET',
[HTTP2_HEADER_PATH]: '/',
[HTTP2_HEADER_AUTHORITY]: 'localhost:8080',
[HTTP2_HEADER_SCHEME]: 'https',
'user-agent': 'node-http2/client',
'custom-header': 'custom-value'
});
req.on('response', (headers) => {
console.log('Response status:', headers[HTTP2_HEADER_STATUS]);
console.log('Response headers:', headers);
});
req.on('data', (chunk) => {
console.log('Received data:', chunk.toString());
});
req.on('end', () => {
client.close();
});
req.end();
HTTP/2 সেটিংস
HTTP/2 বিভিন্ন প্রোটোকল সেটিংস কনফিগার করার অনুমতি দেয়:
const http2 = require('http2');
const fs = require('fs');
const path = require('path');
const options = {
key: fs.readFileSync(path.join(__dirname, 'server.key')),
cert: fs.readFileSync(path.join(__dirname, 'server.crt')),
// HTTP/2 settings
settings: {
// Max concurrent streams per connection
maxConcurrentStreams: 100,
// Initial window size for flow control
initialWindowSize: 1024 * 1024, // 1MB
// Enable server push
enablePush: true
}
};
const server = http2.createSecureServer(options);
server.on('stream', (stream, headers) => {
stream.respond({
'content-type': 'text/html',
':status': 200
});
stream.end('HTTP/2 Server with Custom Settings
');
});
server.listen(8080);
HTTP/1.1 এর সাথে সামঞ্জস্যপূর্ণ
HTTP/2 সার্ভারগুলিও HTTP/1.1 অনুরোধগুলি পরিচালনা করতে পারে, একটি বিরামহীন আপগ্রেড পাথ প্রদান করে:
const http2 = require('http2');
const http = require('http');
const fs = require('fs');
const path = require('path');
// For HTTP/2 secure server
const options = {
key: fs.readFileSync(path.join(__dirname, 'server.key')),
cert: fs.readFileSync(path.join(__dirname, 'server.crt')),
allowHTTP1: true // Allow HTTP/1.1 connections
};
const server = http2.createSecureServer(options);
// Handler function for both HTTP/1.1 and HTTP/2
const handler = (req, res) => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end(`Hello from ${req.httpVersion} server!`);
};
// HTTP/1.1 compatibility request handler
server.on('request', handler);
// HTTP/2 specific stream handler
server.on('stream', (stream, headers) => {
stream.respond({
'content-type': 'text/plain',
':status': 200
});
stream.end(`Hello from HTTP/2 stream API!`);
});
server.listen(8080, () => {
console.log('Server running at https://localhost:8080/');
});
কর্মক্ষমতা প্রতিক্রিয়া
যদিও HTTP/2 পারফরম্যান্সের উন্নতির প্রস্তাব দেয়, তবে আপনার অ্যাপ্লিকেশনটি অপ্টিমাইজ করা গুরুত্বপূর্ণ:
HTTP/2 vs HTTP/1.1
HTTP/2 এবং HTTP/1.1 এর মধ্যে প্রধান পার্থক্য হল:
| বৈশিষ্ট্য | HTTP/1.1 | HTTP/2 |
|---|---|---|
| প্রোটোকল বিন্যাস | পাঠ্য-ভিত্তিক | বাইনারি ভিত্তিক |
| মাল্টিপ্লেক্সিং | না (একাধিক সংযোগ প্রয়োজন) | হ্যাঁ (এক সংযোগে একাধিক স্ট্রীম) |
| হেডার কম্প্রেশন | না | হ্যাঁ (HPACK) |
| সার্ভার পুশ | না | হ্যাঁ |
| প্রবাহ নিয়ন্ত্রণ | মৌলিক | উন্নত, স্ট্রিম থেকে স্ট্রিম |
| অগ্রাধিকার | না | হ্যাঁ |
বাস্তব-বিশ্বের উদাহরণ: একটি সম্পূর্ণ ওয়েবসাইট পরিবেশন করা
HTTP/2 সহ একটি ওয়েবসাইট পরিবেশন করার একটি সম্পূর্ণ উদাহরণ:
const http2 = require('http2');
const fs = require('fs');
const path = require('path');
const mime = require('mime-types');
const options = {
key: fs.readFileSync(path.join(__dirname, 'server.key')),
cert: fs.readFileSync(path.join(__dirname, 'server.crt'))
};
const server = http2.createSecureServer(options);
// Serve files from the public directory
const publicDir = path.join(__dirname, 'public');
server.on('stream', (stream, headers) => {
const reqPath = headers[':path'] === '/' ? '/index.html' : headers[':path'];
const filePath = path.join(publicDir, reqPath);
// Basic security check to prevent path traversal
if (!filePath.startsWith(publicDir)) {
stream.respond({ ':status': 403 });
stream.end('Forbidden');
return;
}
fs.stat(filePath, (err, stats) => {
if (err || !stats.isFile()) {
// File not found
stream.respond({ ':status': 404 });
stream.end('Not found');
return;
}
// Determine content type
const contentType = mime.lookup(filePath) || 'application/octet-stream';
// Serve the file
stream.respond({
'content-type': contentType,
':status': 200
});
const fileStream = fs.createReadStream(filePath);
fileStream.pipe(stream);
fileStream.on('error', (err) => {
console.error('File stream error:', err);
stream.close(http2.constants.NGHTTP2_INTERNAL_ERROR);
});
});
});
server.listen(8080, () => {
console.log('HTTP/2 server running at https://localhost:8080/');
});
দ্রষ্টব্য:
এই উদাহরণের জন্য mime-টাইপ প্যাকেজ প্রয়োজন:npm install mime-types
উন্নত স্ট্রিম ম্যানেজমেন্ট
HTTP/2 এর স্ট্রিম ম্যানেজমেন্ট ক্ষমতা একাধিক সমসাময়িক অনুরোধের দক্ষ পরিচালনার অনুমতি দেয়। এখানে একটি উন্নত উদাহরণ রয়েছে যা স্ট্রিম অগ্রাধিকার এবং প্রবাহ নিয়ন্ত্রণ প্রদর্শন করে:
const http2 = require('http2');
const fs = require('fs');
// Create a server with custom settings
const server = http2.createSecureServer({
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt'),
settings: {
initialWindowSize: 65535, // 64KB initial window
maxConcurrentStreams: 100,
enablePush: true
}
});
server.on('stream', (stream, headers) => {
// Get priority information
const weight = stream.priority && stream.priority.weight || 1;
const parent = stream.priority && stream.priority.parent ? 'with parent' : 'no parent';
console.log(`New stream ${stream.id} (weight: ${weight}, ${parent})`);
// Handle different priority levels
if (headers[':path'] === '/high-priority') {
stream.priority({ weight: 256, exclusive: true });
stream.respond({ ':status': 200, 'content-type': 'text/plain' });
stream.end('High priority content');
} else {
// Default priority
stream.respond({ ':status': 200, 'content-type': 'text/plain' });
stream.end('Standard priority content');
}
// Handle stream errors
stream.on('error', (error) => {
console.error(`Stream ${stream.id} error:`, error);
stream.end();
});
// Handle stream close
stream.on('close', () => {
console.log(`Stream ${stream.id} closed`);
});
});
server.listen(8443);
ত্রুটি হ্যান্ডলিং এবং ডিবাগিং
সঠিক ত্রুটি পরিচালনা নির্ভরযোগ্য HTTP/2 অ্যাপ্লিকেশনের জন্য গুরুত্বপূর্ণ। বিস্তারিত ত্রুটি হ্যান্ডলিং কিভাবে বাস্তবায়ন করতে হয় তা এখানে:
const http2 = require('http2');
const fs = require('fs');
const { promisify } = require('util');
const readFile = promisify(fs.readFile);
async function startServer() {
try {
const [key, cert] = await Promise.all([
readFile('server.key'),
readFile('server.crt')
]);
const server = http2.createSecureServer({ key, cert });
// Global error handler
server.on('error', (err) => {
console.error('Server error:', err);
// Implement proper error recovery
});
// Handle uncaught exceptions
process.on('uncaughtException', (err) => {
console.error('Uncaught exception:', err);
// Graceful shutdown
server.close(() => process.exit(1));
});
// Handle unhandled promise rejections
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason);
});
// Stream handler with error boundaries
server.on('stream', (stream, headers) => {
try {
// Simulate async operation
setTimeout(() => {
try {
if (Math.random() > 0.8) {
throw new Error('Random error for demonstration');
}
stream.respond({ ':status': 200 });
stream.end('Success!');
} catch (err) {
handleStreamError(stream, err);
}
}, 100);
} catch (err) {
handleStreamError(stream, err);
}
});
function handleStreamError(stream, error) {
console.error('Stream error:', error);
if (!stream.destroyed) {
stream.respond({
':status': 500,
'content-type': 'text/plain'
});
stream.end('Internal Server Error');
}
}
server.listen(8443, () => {
console.log('Server running on https://localhost:8443');
});
} catch (err) {
console.error('Failed to start server:', err);
process.exit(1);
}
}
startServer();
কর্মক্ষমতা অপ্টিমাইজেশান
HTTP/2 কর্মক্ষমতা অপ্টিমাইজ করার জন্য এর অনন্য বৈশিষ্ট্য বোঝা প্রয়োজন। এখানে মূল কৌশলগুলি রয়েছে:
1. সংযোগ পুলিং
const http2 = require('http2');
const { URL } = require('url');
class HTTP2ConnectionPool {
constructor() {
this.connections = new Map();
}
async getConnection(url) {
const { origin } = new URL(url);
if (!this.connections.has(origin)) {
const client = http2.connect(origin, {
rejectUnauthorized: false // Only for development
});
// Handle connection errors
client.on('error', (err) => {
console.error('Connection error:', err);
this.connections.delete(origin);
});
// Remove connection when closed
client.on('close', () => {
this.connections.delete(origin);
});
this.connections.set(origin, {
client,
lastUsed: Date.now(),
inUse: 0
});
}
const conn = this.connections.get(origin);
conn.lastUsed = Date.now();
conn.inUse++;
return {
client: conn.client,
release: () => {
conn.inUse--;
}
};
}
// Clean up idle connections
startCleanup(interval = 30000) {
setInterval(() => {
const now = Date.now();
for (const [origin, conn] of this.connections.entries()) {
if (conn.inUse === 0 && (now - conn.lastUsed) > 60000) {
conn.client.destroy();
this.connections.delete(origin);
}
}
}, interval);
}
}
// Usage example
const pool = new HTTP2ConnectionPool();
pool.startCleanup();
async function makeRequest(url) {
const { client, release } = await pool.getConnection(url);
return new Promise((resolve, reject) => {
const req = client.request({ ':path': new URL(url).pathname });
let data = '';
req.on('response', (headers) => {
console.log('Status:', headers[':status']);
});
req.on('data', (chunk) => data += chunk);
req.on('end', () => {
release();
resolve(data);
});
req.on('error', (err) => {
release();
reject(err);
});
req.end();
});
}
2. হেডার কম্প্রেশন অপ্টিমাইজেশান
HTTP/2 হেডারের জন্য HPACK কম্প্রেশন ব্যবহার করে। এর সাথে অপ্টিমাইজ করুন:
নিরাপত্তা সেরা অনুশীলন
HTTP/2 ব্যবহার করার সময়, এই নিরাপত্তা অনুশীলনগুলি অনুসরণ করুন:
const http2 = require('http2');
const fs = require('fs');
const { createSecureContext } = require('tls');
// Security headers middleware
function securityHeaders(req, res, next) {
// Set security headers
res.setHeader('X-Content-Type-Options', 'nosniff');
res.setHeader('X-Frame-Options', 'DENY');
res.setHeader('X-XSS-Protection', '1; mode=block');
res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
res.setHeader('Content-Security-Policy', "default-src 'self'");
// Remove server header
res.removeHeader('X-Powered-By');
next();
}
// Create secure server with modern TLS settings
const options = {
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt'),
secureOptions:
require('constants').SSL_OP_NO_SSLv3 |
require('constants').SSL_OP_NO_TLSv1 |
require('constants').SSL_OP_NO_TLSv1_1,
ciphers: [
'TLS_AES_256_GCM_SHA384',
'TLS_CHACHA20_POLY1305_SHA256',
'TLS_AES_128_GCM_SHA256'
].join(':'),
minVersion: 'TLSv1.3',
maxVersion: 'TLSv1.3',
// OCSP Stapling
requestCert: false,
rejectUnauthorized: true
};
const server = http2.createSecureServer(options);
// Apply security middleware
server.on('request', (req, res) => {
securityHeaders(req, res, () => {
// Request handling logic
res.setHeader('Content-Type', 'text/plain');
res.end('Secure HTTP/2 Response');
});
});
// Handle TLS errors
server.on('tlsClientError', (err, tlsSocket) => {
console.error('TLS Error:', err);
tlsSocket.destroy();
});
server.listen(8443);
বাস্তব-বিশ্ব ব্যবহারের ক্ষেত্রে
1. HTTP/2 সহ API গেটওয়ে
HTTP/2 সহ একটি উচ্চ-পারফরম্যান্স API গেটওয়ে কনফিগার করা:
const http2 = require('http2');
const { URL } = require('url');
const path = require('path');
const fs = require('fs');
// Service registry
const services = {
'/users': 'http://users-service:3000',
'/products': 'http://products-service:3000',
'/orders': 'http://orders-service:3000'
};
// Create HTTP/2 server
const server = http2.createSecureServer({
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt')
});
// Route requests to appropriate services
server.on('stream', (stream, headers) => {
const path = headers[':path'];
const method = headers[':method'];
try {
// Find matching service
const servicePath = Object.keys(services).find(prefix =>
path.startsWith(prefix)
);
if (!servicePath) {
stream.respond({ ':status': 404 });
return stream.end('Not Found');
}
const targetUrl = new URL(path.slice(servicePath.length), services[servicePath]);
// Forward request to target service
const client = http2.connect(targetUrl.origin);
const req = client.request({
...headers,
':path': targetUrl.pathname + targetUrl.search,
':method': method,
':authority': targetUrl.host
});
// Pipe the response back to client
req.pipe(stream);
stream.pipe(req);
// Handle errors
req.on('error', (err) => {
console.error('Request error:', err);
if (!stream.destroyed) {
stream.respond({ ':status': 502 });
stream.end('Bad Gateway');
}
});
stream.on('error', (err) => {
console.error('Stream error:', err);
req.destroy();
});
} catch (err) {
console.error('Gateway error:', err);
if (!stream.destroyed) {
stream.respond({ ':status': 500 });
stream.end('Internal Server Error');
}
}
});
server.listen(443);
2. রিয়েল-টাইম ডেটা স্ট্রিমিং
HTTP/2 এর সাথে দক্ষ রিয়েল-টাইম ডেটা স্ট্রিমিং:
const http2 = require('http2');
const fs = require('fs');
const server = http2.createSecureServer({
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt')
});
// In-memory storage for active streams
const streams = new Set();
// Broadcast data to all connected clients
function broadcast(data) {
const payload = JSON.stringify(data);
for (const stream of streams) {
try {
stream.write(`data: ${payload}\n\n`);
} catch (err) {
console.error('Stream write error:', err);
streams.delete(stream);
}
}
}
// Simulate data updates
setInterval(() => {
broadcast({
time: new Date().toISOString(),
value: Math.random() * 100
});
}, 1000);
server.on('stream', (stream, headers) => {
// Only handle GET requests
if (headers[':method'] !== 'GET') {
stream.respond({ ':status': 405 });
return stream.end();
}
// Set up Server-Sent Events headers
stream.respond({
'content-type': 'text/event-stream',
'cache-control': 'no-cache',
'connection': 'keep-alive',
':status': 200
});
// Add to active streams
streams.add(stream);
// Handle client disconnect
stream.on('close', () => {
streams.delete(stream);
});
// Send initial data
stream.write('event: connect\ndata: Connected\n\n');
});
server.listen(8443, () => {
console.log('HTTP/2 Server running on https://localhost:8443');
});