const https = require('https');
const fs = require('fs');
const path = require('path');
const url = require('url');
// For demo purposes, we'll use self-signed certificates
// In production, use certificates from a trusted CA
const options = {
key: fs.readFileSync(path.join(__dirname, 'selfsigned.key')),
cert: fs.readFileSync(path.join(__dirname, 'selfsigned.crt')),
// Enable HTTP/2 if available
// This requires Node.js 8.4.0 or later
// ALPNProtocols: ['h2', 'http/1.1']
};
// Simple middleware system
const middlewares = [
// Logging middleware
(req, res, next) => {
console.log(`[${new Date().toISOString()}] ${req.method} ${req.url}`);
next();
},
// Authentication middleware (simplified)
(req, res, next) => {
const auth = req.headers.authorization;
const protectedRoutes = ['/admin', '/dashboard'];
if (protectedRoutes.some(route => req.url.startsWith(route))) {
if (!auth || auth !== 'Bearer secret-token') {
res.statusCode = 401;
res.setHeader('WWW-Authenticate', 'Bearer');
return res.end('Unauthorized');
}
}
next();
}
];
// Route handlers
const routes = {
'/': (req, res) => {
res.setHeader('Content-Type', 'text/html');
res.end(`
<!DOCTYPE html>
<html>
<head><title>HTTPS Server</title></head>
<body>
<h1>Welcome to the HTTPS Server</h1>
<p>Try these endpoints:</p>
<ul>
<li><a href="/api/time">/api/time</a> - Get current server time</li>
<li><a href="/api/headers">/api/headers</a> - View request headers</li>
<li><a href="/admin">/admin</a> - Protected route (use Authorization: Bearer secret-token)</li>
</ul>
</body>
</html>
`);
},
'/api/time': (req, res) => {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
timestamp: new Date().toISOString(),
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
}, null, 2));
},
'/api/headers': (req, res) => {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
method: req.method,
url: req.url,
headers: req.headers
}, null, 2));
},
'/admin': (req, res) => {
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
message: 'Admin Dashboard',
authorized: true,
user: 'admin',
permissions: ['read', 'write', 'delete']
}, null, 2));
},
'404': (req, res) => {
res.statusCode = 404;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({
error: 'Not Found',
message: `The requested URL ${req.url} was not found on this server.`
}, null, 2));
}
};
// Create HTTPS server
const server = https.createServer(options, (req, res) => {
// Parse URL
const parsedUrl = url.parse(req.url, true);
const pathname = parsedUrl.pathname;
// Attach parsed URL to request object
req.parsedUrl = parsedUrl;
// Execute middlewares
const executeMiddlewares = (index = 0) => {
if (index < middlewares.length) {
middlewares[index](req, res, () => executeMiddlewares(index + 1));
} else {
// Find and execute route handler
const route = Object.keys(routes).find(route => route === pathname) || '404';
routes[route](req, res);
}
};
executeMiddlewares();
});
// Server events
server.on('listening', () => {
const addr = server.address();
console.log(`HTTPS server listening on https://localhost:${addr.port}`);
console.log('\nAvailable endpoints:');
console.log(`- https://localhost:${addr.port}/`);
console.log(`- https://localhost:${addr.port}/api/time`);
console.log(`- https://localhost:${addr.port}/api/headers`);
console.log(`- https://localhost:${addr.port}/admin (requires auth)`);
});
server.on('error', (err) => {
console.error('Server error:', err);
if (err.code === 'EACCES') {
console.error('Error: Permission denied. Try using a port above 1024.');
} else if (err.code === 'EADDRINUSE') {
console.error('Error: Port already in use.');
}
process.exit(1);
});
// Graceful shutdown
process.on('SIGTERM', () => {
console.log('\nSIGTERM received. Shutting down gracefully...');
server.close(() => {
console.log('Server closed');
process.exit(0);
});
});
// Start the server
const PORT = 3443;
server.listen(PORT, () => {
console.log(`Server started on port ${PORT}`);
console.log('Note: Using self-signed certificate. Your browser may show a security warning.');
});