claude made a website

This commit is contained in:
whaffman 2025-10-01 18:03:00 +02:00
parent bcd33dacd7
commit ab83c02fd2
19 changed files with 3281 additions and 8 deletions

View File

@ -50,9 +50,9 @@ server {
server { server {
listen 8081; listen 8081;
host 127.0.0.1; host 127.0.0.1;
server_name mylocal; server_name localhost;
root /var/www/html2; root /www;
index index.html index2.htm; index index.html index2.htm;
error_page 400 /400.html; error_page 400 /400.html;
@ -68,6 +68,7 @@ server {
location / { location / {
autoindex off; autoindex off;
root www;
index index.html; index index.html;
allowed_methods GET POST DELETE; allowed_methods GET POST DELETE;
} }

View File

@ -8,10 +8,10 @@
class ErrorHandler class ErrorHandler
{ {
public: public:
static std::unique_ptr<HttpResponse> getErrorResponse(int statusCode, AConfig *config = nullptr); static std::unique_ptr<HttpResponse> getErrorResponse(int statusCode, const AConfig *config = nullptr);
private: private:
static std::string generateErrorPage(int statusCode, AConfig *config = nullptr); static std::string generateErrorPage(int statusCode, const AConfig *config = nullptr);
static std::string generateDefaultErrorPage(int statusCode); static std::string generateDefaultErrorPage(int statusCode);
static std::string getErrorPageFile(const std::string &path); static std::string getErrorPageFile(const std::string &path);
}; };

View File

@ -12,7 +12,7 @@
#include <sstream> // for basic_stringstream #include <sstream> // for basic_stringstream
#include <string> // for basic_string, operator+, allocator, char_traits, string, to_string #include <string> // for basic_string, operator+, allocator, char_traits, string, to_string
std::unique_ptr<HttpResponse> ErrorHandler::getErrorResponse(int statusCode, AConfig *config) std::unique_ptr<HttpResponse> ErrorHandler::getErrorResponse(int statusCode, const AConfig *config)
{ {
std::string statusMessage = Http::getStatusCodeReason(statusCode); std::string statusMessage = Http::getStatusCodeReason(statusCode);
Log::warning("Generating error response: " + std::to_string(statusCode) + " " + statusMessage); Log::warning("Generating error response: " + std::to_string(statusCode) + " " + statusMessage);
@ -26,7 +26,7 @@ std::unique_ptr<HttpResponse> ErrorHandler::getErrorResponse(int statusCode, ACo
return response; return response;
} }
std::string ErrorHandler::generateErrorPage(int statusCode, AConfig *config) std::string ErrorHandler::generateErrorPage(int statusCode, const AConfig *config)
{ {
Log::trace(LOCATION); Log::trace(LOCATION);
if (config == nullptr) if (config == nullptr)

View File

@ -79,7 +79,7 @@ std::unique_ptr<HttpResponse> FileHandler::getResponse() const
Log::debug("Serving file: " + filepath + " with MIME type: " + mimeType); Log::debug("Serving file: " + filepath + " with MIME type: " + mimeType);
if (fileData.empty()) if (fileData.empty())
{ {
return ErrorHandler::getErrorResponse(404); return ErrorHandler::getErrorResponse(404, location_);
} }
response->setBody(std::string(fileData.begin(), fileData.end())); response->setBody(std::string(fileData.begin(), fileData.end()));
} }

View File

@ -33,7 +33,7 @@ std::unique_ptr<HttpResponse> Router::handleRequest(const HttpRequest &request)
const LocationConfig *location = uriParser.getLocation(); const LocationConfig *location = uriParser.getLocation();
if (location == nullptr) if (location == nullptr)
{ {
return ErrorHandler::getErrorResponse(404); return ErrorHandler::getErrorResponse(404, config);
} }
FileHandler fileHandler(location, uriParser); FileHandler fileHandler(location, uriParser);

276
www/404.html Normal file
View File

@ -0,0 +1,276 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>404 - Page Not Found | WebServ</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
background: linear-gradient(135deg, #0f172a, #1e293b);
color: #f8fafc;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
.error-container {
max-width: 600px;
padding: 2rem;
}
.error-code {
font-size: 8rem;
font-weight: 800;
background: linear-gradient(135deg, #ef4444, #dc2626);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 1rem;
line-height: 1;
}
.error-title {
font-size: 2rem;
font-weight: 600;
margin-bottom: 1rem;
color: #f1f5f9;
}
.error-message {
font-size: 1.1rem;
color: #cbd5e1;
margin-bottom: 2rem;
line-height: 1.6;
}
.error-actions {
display: flex;
gap: 1rem;
justify-content: center;
flex-wrap: wrap;
}
.btn {
padding: 0.75rem 1.5rem;
border-radius: 0.5rem;
text-decoration: none;
font-weight: 600;
transition: all 0.3s ease;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.btn-primary {
background: linear-gradient(135deg, #2563eb, #1d4ed8);
color: white;
border: none;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(37, 99, 235, 0.3);
}
.btn-secondary {
background: transparent;
color: #cbd5e1;
border: 1px solid #475569;
}
.btn-secondary:hover {
background: #334155;
border-color: #64748b;
color: #f1f5f9;
}
.error-details {
margin-top: 3rem;
padding: 1.5rem;
background: rgba(30, 41, 59, 0.5);
border-radius: 0.5rem;
border: 1px solid #475569;
text-align: left;
}
.error-details h3 {
color: #f1f5f9;
margin-bottom: 1rem;
font-size: 1.1rem;
}
.error-details p {
color: #94a3b8;
font-size: 0.9rem;
margin-bottom: 0.5rem;
font-family: 'Fira Code', monospace;
}
.server-info {
margin-top: 2rem;
padding-top: 2rem;
border-top: 1px solid #475569;
color: #64748b;
font-size: 0.9rem;
}
@media (max-width: 480px) {
.error-code {
font-size: 5rem;
}
.error-title {
font-size: 1.5rem;
}
.error-actions {
flex-direction: column;
align-items: center;
}
.btn {
width: 100%;
max-width: 200px;
justify-content: center;
}
}
.floating-shapes {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
overflow: hidden;
pointer-events: none;
z-index: -1;
}
.shape {
position: absolute;
background: rgba(37, 99, 235, 0.1);
border-radius: 50%;
animation: float 20s infinite ease-in-out;
}
.shape:nth-child(1) {
width: 100px;
height: 100px;
top: 10%;
left: 10%;
animation-delay: 0s;
}
.shape:nth-child(2) {
width: 150px;
height: 150px;
top: 60%;
right: 10%;
animation-delay: 7s;
}
.shape:nth-child(3) {
width: 80px;
height: 80px;
bottom: 20%;
left: 20%;
animation-delay: 14s;
}
@keyframes float {
0%, 100% {
transform: translateY(0) rotate(0deg);
opacity: 0.3;
}
50% {
transform: translateY(-30px) rotate(180deg);
opacity: 0.6;
}
}
</style>
</head>
<body>
<div class="floating-shapes">
<div class="shape"></div>
<div class="shape"></div>
<div class="shape"></div>
</div>
<div class="error-container">
<div class="error-code">404</div>
<h1 class="error-title">Page Not Found</h1>
<p class="error-message">
The page you're looking for doesn't exist or has been moved.
Don't worry, even the best servers sometimes lose track of a page or two.
</p>
<div class="error-actions">
<a href="/" class="btn btn-primary">
🏠 Go Home
</a>
<a href="javascript:history.back()" class="btn btn-secondary">
← Go Back
</a>
</div>
<div class="error-details">
<h3>Technical Details</h3>
<p>Request: <span id="request-url"></span></p>
<p>Method: GET</p>
<p>Status: 404 Not Found</p>
<p>Timestamp: <span id="timestamp"></span></p>
<p>Referrer: <span id="referrer"></span></p>
</div>
<div class="server-info">
<p><strong>WebServ</strong> - High Performance C++ Web Server</p>
<p>If this error persists, please contact the site administrator.</p>
</div>
</div>
<script>
// Populate error details
document.getElementById('request-url').textContent = window.location.pathname;
document.getElementById('timestamp').textContent = new Date().toISOString();
document.getElementById('referrer').textContent = document.referrer || 'Direct access';
// Add some interactivity
const shapes = document.querySelectorAll('.shape');
let mouseX = 0;
let mouseY = 0;
document.addEventListener('mousemove', (e) => {
mouseX = e.clientX / window.innerWidth;
mouseY = e.clientY / window.innerHeight;
shapes.forEach((shape, index) => {
const speed = (index + 1) * 0.5;
const x = mouseX * speed * 10;
const y = mouseY * speed * 10;
shape.style.transform = `translate(${x}px, ${y}px)`;
});
});
// Log error for debugging (in development)
if (window.location.hostname === 'localhost') {
console.log('404 Error Details:', {
url: window.location.href,
path: window.location.pathname,
referrer: document.referrer,
userAgent: navigator.userAgent,
timestamp: new Date().toISOString()
});
}
</script>
</body>
</html>

285
www/50x.html Normal file
View File

@ -0,0 +1,285 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Server Error | WebServ</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
background: linear-gradient(135deg, #0f172a, #1e293b);
color: #f8fafc;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
}
.error-container {
max-width: 600px;
padding: 2rem;
}
.error-code {
font-size: 6rem;
font-weight: 800;
background: linear-gradient(135deg, #f59e0b, #d97706);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 1rem;
line-height: 1;
}
.error-title {
font-size: 2rem;
font-weight: 600;
margin-bottom: 1rem;
color: #f1f5f9;
}
.error-message {
font-size: 1.1rem;
color: #cbd5e1;
margin-bottom: 2rem;
line-height: 1.6;
}
.error-actions {
display: flex;
gap: 1rem;
justify-content: center;
flex-wrap: wrap;
}
.btn {
padding: 0.75rem 1.5rem;
border-radius: 0.5rem;
text-decoration: none;
font-weight: 600;
transition: all 0.3s ease;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.btn-primary {
background: linear-gradient(135deg, #2563eb, #1d4ed8);
color: white;
border: none;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(37, 99, 235, 0.3);
}
.btn-secondary {
background: transparent;
color: #cbd5e1;
border: 1px solid #475569;
}
.btn-secondary:hover {
background: #334155;
border-color: #64748b;
color: #f1f5f9;
}
.error-details {
margin-top: 3rem;
padding: 1.5rem;
background: rgba(30, 41, 59, 0.5);
border-radius: 0.5rem;
border: 1px solid #475569;
text-align: left;
}
.error-details h3 {
color: #f1f5f9;
margin-bottom: 1rem;
font-size: 1.1rem;
}
.error-details p {
color: #94a3b8;
font-size: 0.9rem;
margin-bottom: 0.5rem;
font-family: 'Fira Code', monospace;
}
.server-info {
margin-top: 2rem;
padding-top: 2rem;
border-top: 1px solid #475569;
color: #64748b;
font-size: 0.9rem;
}
.status-indicator {
display: inline-flex;
align-items: center;
gap: 0.5rem;
margin: 1rem 0;
padding: 1rem;
background: rgba(245, 158, 11, 0.1);
border: 1px solid #f59e0b;
border-radius: 0.5rem;
}
.status-dot {
width: 12px;
height: 12px;
background: #f59e0b;
border-radius: 50%;
animation: pulse 2s infinite;
}
@keyframes pulse {
0% {
opacity: 1;
}
50% {
opacity: 0.5;
}
100% {
opacity: 1;
}
}
@media (max-width: 480px) {
.error-code {
font-size: 4rem;
}
.error-title {
font-size: 1.5rem;
}
.error-actions {
flex-direction: column;
align-items: center;
}
.btn {
width: 100%;
max-width: 200px;
justify-content: center;
}
}
</style>
</head>
<body>
<div class="error-container">
<div class="error-code">5XX</div>
<h1 class="error-title">Server Error</h1>
<p class="error-message">
We're experiencing some technical difficulties. Our team has been notified
and is working to resolve the issue as quickly as possible.
</p>
<div class="status-indicator">
<div class="status-dot"></div>
<span>Server is being restored...</span>
</div>
<div class="error-actions">
<a href="/" class="btn btn-primary">
🏠 Go Home
</a>
<a href="javascript:location.reload()" class="btn btn-secondary">
🔄 Refresh Page
</a>
</div>
<div class="error-details">
<h3>Error Information</h3>
<p>Request: <span id="request-url"></span></p>
<p>Method: GET</p>
<p>Status: <span id="error-code">500</span> Internal Server Error</p>
<p>Timestamp: <span id="timestamp"></span></p>
<p>Request ID: <span id="request-id"></span></p>
</div>
<div class="server-info">
<p><strong>WebServ</strong> - High Performance C++ Web Server</p>
<p>Error ID: <span id="error-id"></span></p>
<p>If this problem persists, please contact our support team.</p>
</div>
</div>
<script>
// Generate random error ID
function generateErrorId() {
return 'ERR-' + Math.random().toString(36).substr(2, 9).toUpperCase();
}
// Generate random request ID
function generateRequestId() {
return 'REQ-' + Date.now().toString(36) + Math.random().toString(36).substr(2, 5);
}
// Populate error details
document.getElementById('request-url').textContent = window.location.pathname;
document.getElementById('timestamp').textContent = new Date().toISOString();
document.getElementById('request-id').textContent = generateRequestId();
document.getElementById('error-id').textContent = generateErrorId();
// Auto-refresh after 30 seconds
let countdown = 30;
const refreshBtn = document.querySelector('.btn-secondary');
const originalText = refreshBtn.innerHTML;
function updateCountdown() {
if (countdown > 0) {
refreshBtn.innerHTML = `🔄 Refresh Page (${countdown}s)`;
countdown--;
setTimeout(updateCountdown, 1000);
} else {
refreshBtn.innerHTML = originalText;
location.reload();
}
}
// Start countdown after 5 seconds
setTimeout(updateCountdown, 5000);
// Log error for debugging
console.error('Server Error Details:', {
url: window.location.href,
path: window.location.pathname,
userAgent: navigator.userAgent,
timestamp: new Date().toISOString(),
errorId: document.getElementById('error-id').textContent,
requestId: document.getElementById('request-id').textContent
});
// Try to detect the specific error code from URL parameters
const urlParams = new URLSearchParams(window.location.search);
const errorCode = urlParams.get('code') || '500';
document.getElementById('error-code').textContent = errorCode;
// Update title and message based on error code
const errorMessages = {
'500': 'Internal Server Error - Something went wrong on our end.',
'502': 'Bad Gateway - The server received an invalid response.',
'503': 'Service Unavailable - The server is temporarily unavailable.',
'504': 'Gateway Timeout - The server took too long to respond.'
};
if (errorMessages[errorCode]) {
document.querySelector('.error-message').textContent = errorMessages[errorCode];
}
// Update the main error code display
document.querySelector('.error-code').textContent = errorCode;
</script>
</body>
</html>

44
www/api/health.json Normal file
View File

@ -0,0 +1,44 @@
{
"status": "healthy",
"timestamp": "2025-01-27T10:30:00.000Z",
"checks": {
"database": {
"status": "up",
"response_time_ms": 2.1,
"last_check": "2025-01-27T10:29:55.000Z"
},
"memory": {
"status": "ok",
"usage_percent": 65.4,
"available_mb": 5632,
"threshold_percent": 80
},
"disk": {
"status": "ok",
"usage_percent": 42.1,
"available_gb": 125.7,
"threshold_percent": 90
},
"network": {
"status": "up",
"active_connections": 127,
"max_connections": 10000,
"bandwidth_utilization_percent": 15.2
},
"services": {
"web_server": {
"status": "running",
"port": 8080,
"uptime_seconds": 172800
},
"log_service": {
"status": "running",
"last_rotation": "2025-01-27T00:00:00.000Z"
}
}
},
"overall_status": "healthy",
"uptime_seconds": 172800,
"version": "1.0.0",
"environment": "production"
}

57
www/api/info.json Normal file
View File

@ -0,0 +1,57 @@
{
"server": "WebServ",
"version": "1.0.0",
"status": "running",
"uptime": "2d 14h 32m",
"build": {
"compiler": "clang++ 12.0.1",
"standard": "C++20",
"optimization": "O3",
"build_type": "release"
},
"connections": {
"active": 127,
"total": 45892,
"max_concurrent": 10000
},
"performance": {
"requests_per_second": 1542,
"avg_response_time_ms": 1.2,
"memory_usage_mb": 45.2,
"cpu_usage_percent": 12.5
},
"features": [
"HTTP/1.1",
"Keep-Alive",
"Chunked Transfer Encoding",
"Virtual Hosts",
"Static File Serving",
"Directory Listing",
"Custom Error Pages",
"Configuration Validation",
"Epoll Event Loop",
"Multi-threaded Processing"
],
"supported_methods": [
"GET",
"POST",
"PUT",
"DELETE",
"HEAD",
"OPTIONS"
],
"configuration": {
"config_file": "webserv.conf",
"document_root": "./www",
"index_files": ["index.html", "index.htm"],
"error_log": "logs/error.log",
"access_log": "logs/access.log"
},
"system": {
"os": "Linux",
"architecture": "x86_64",
"cores": 8,
"total_memory_gb": 16.0,
"available_memory_gb": 12.3
}
}

48
www/api/users.json Normal file
View File

@ -0,0 +1,48 @@
{
"status": "success",
"timestamp": "2025-01-27T10:30:00.000Z",
"response_time_ms": 1.8,
"data": {
"users": [
{
"id": 1,
"username": "admin",
"email": "admin@webserv.local",
"role": "administrator",
"active": true,
"created_at": "2025-01-01T00:00:00.000Z"
},
{
"id": 2,
"username": "developer",
"email": "dev@webserv.local",
"role": "developer",
"active": true,
"created_at": "2025-01-15T09:30:00.000Z"
},
{
"id": 3,
"username": "guest",
"email": "guest@webserv.local",
"role": "user",
"active": false,
"created_at": "2025-01-20T14:22:00.000Z"
}
],
"total_count": 3,
"active_count": 2
},
"pagination": {
"page": 1,
"per_page": 10,
"total_pages": 1,
"has_next": false,
"has_prev": false
},
"meta": {
"api_version": "v1",
"server": "WebServ/1.0",
"cache_hit": false,
"query_time_ms": 0.5
}
}

653
www/css/style.css Normal file
View File

@ -0,0 +1,653 @@
:root {
--primary-color: #2563eb;
--primary-dark: #1d4ed8;
--secondary-color: #64748b;
--accent-color: #f59e0b;
--success-color: #10b981;
--error-color: #ef4444;
--warning-color: #f59e0b;
--background-color: #0f172a;
--surface-color: #1e293b;
--surface-light: #334155;
--text-primary: #f8fafc;
--text-secondary: #cbd5e1;
--text-muted: #94a3b8;
--border-color: #475569;
--shadow-color: rgba(0, 0, 0, 0.3);
--gradient-primary: linear-gradient(135deg, var(--primary-color), var(--primary-dark));
--gradient-secondary: linear-gradient(135deg, var(--surface-color), var(--surface-light));
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
scroll-behavior: smooth;
}
body {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
line-height: 1.6;
color: var(--text-primary);
background: var(--background-color);
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
}
/* Navigation */
.navbar {
position: fixed;
top: 0;
width: 100%;
background: rgba(15, 23, 42, 0.95);
backdrop-filter: blur(10px);
border-bottom: 1px solid var(--border-color);
z-index: 1000;
transition: background 0.3s ease;
}
.nav-container {
max-width: 1200px;
margin: 0 auto;
padding: 1rem 2rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.nav-logo h2 {
color: var(--primary-color);
font-weight: 700;
font-size: 1.5rem;
}
.nav-menu {
display: flex;
gap: 2rem;
}
.nav-link {
color: var(--text-secondary);
text-decoration: none;
font-weight: 500;
transition: color 0.3s ease;
position: relative;
}
.nav-link:hover {
color: var(--primary-color);
}
.nav-link::after {
content: '';
position: absolute;
bottom: -5px;
left: 0;
width: 0;
height: 2px;
background: var(--primary-color);
transition: width 0.3s ease;
}
.nav-link:hover::after {
width: 100%;
}
.hamburger {
display: none;
flex-direction: column;
cursor: pointer;
}
.bar {
width: 25px;
height: 3px;
background: var(--text-primary);
margin: 3px 0;
transition: 0.3s;
}
/* Hero Section */
.hero {
min-height: 100vh;
display: flex;
align-items: center;
background: var(--gradient-secondary);
position: relative;
overflow: hidden;
}
.hero::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 1000"><defs><radialGradient id="a" cx="50%" cy="50%"><stop offset="0%" stop-color="%23ffffff" stop-opacity="0.1"/><stop offset="100%" stop-color="%23ffffff" stop-opacity="0"/></radialGradient></defs><circle cx="200" cy="200" r="100" fill="url(%23a)"/><circle cx="800" cy="300" r="150" fill="url(%23a)"/><circle cx="400" cy="700" r="120" fill="url(%23a)"/></svg>');
opacity: 0.5;
pointer-events: none;
}
.hero-container {
max-width: 1200px;
margin: 0 auto;
padding: 0 2rem;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 4rem;
align-items: center;
}
.hero-content {
z-index: 2;
}
.hero-title {
font-size: 4rem;
font-weight: 800;
background: var(--gradient-primary);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 1rem;
line-height: 1.1;
}
.hero-subtitle {
font-size: 1.5rem;
color: var(--text-secondary);
margin-bottom: 1rem;
font-weight: 600;
}
.hero-description {
font-size: 1.1rem;
color: var(--text-muted);
margin-bottom: 2rem;
line-height: 1.7;
}
.hero-buttons {
display: flex;
gap: 1rem;
}
.btn {
padding: 0.875rem 2rem;
border-radius: 0.5rem;
text-decoration: none;
font-weight: 600;
font-size: 1rem;
transition: all 0.3s ease;
display: inline-flex;
align-items: center;
justify-content: center;
border: 2px solid transparent;
}
.btn-primary {
background: var(--gradient-primary);
color: white;
box-shadow: 0 4px 15px rgba(37, 99, 235, 0.3);
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 8px 25px rgba(37, 99, 235, 0.4);
}
.btn-secondary {
background: transparent;
color: var(--text-primary);
border-color: var(--border-color);
}
.btn-secondary:hover {
background: var(--surface-light);
border-color: var(--primary-color);
color: var(--primary-color);
}
/* Code Preview */
.hero-image {
position: relative;
z-index: 2;
}
.code-preview {
background: var(--surface-color);
border-radius: 1rem;
border: 1px solid var(--border-color);
box-shadow: 0 20px 40px var(--shadow-color);
overflow: hidden;
}
.code-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem 1.5rem;
background: var(--surface-light);
border-bottom: 1px solid var(--border-color);
}
.code-dots {
display: flex;
gap: 0.5rem;
}
.dot {
width: 12px;
height: 12px;
border-radius: 50%;
}
.dot.red { background: #ef4444; }
.dot.yellow { background: #f59e0b; }
.dot.green { background: #10b981; }
.code-title {
color: var(--text-secondary);
font-size: 0.875rem;
font-weight: 500;
}
.code-content {
padding: 1.5rem;
font-family: 'Fira Code', 'JetBrains Mono', monospace;
font-size: 0.875rem;
line-height: 1.5;
color: var(--text-secondary);
}
.code-content pre {
margin: 0;
}
/* Sections */
.section-title {
font-size: 2.5rem;
font-weight: 700;
text-align: center;
margin-bottom: 3rem;
color: var(--text-primary);
}
/* Features Section */
.features {
padding: 6rem 0;
background: var(--background-color);
}
.features-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 2rem;
}
.feature-card {
background: var(--surface-color);
padding: 2rem;
border-radius: 1rem;
border: 1px solid var(--border-color);
text-align: center;
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.feature-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 30px var(--shadow-color);
}
.feature-icon {
font-size: 3rem;
margin-bottom: 1rem;
display: block;
}
.feature-card h3 {
font-size: 1.25rem;
font-weight: 600;
margin-bottom: 1rem;
color: var(--text-primary);
}
.feature-card p {
color: var(--text-muted);
line-height: 1.6;
}
/* Documentation Section */
.documentation {
padding: 6rem 0;
background: var(--surface-color);
}
.docs-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 2rem;
}
.docs-card {
background: var(--background-color);
padding: 2rem;
border-radius: 1rem;
border: 1px solid var(--border-color);
transition: transform 0.3s ease;
}
.docs-card:hover {
transform: translateY(-3px);
}
.docs-card h3 {
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 1rem;
color: var(--text-primary);
}
.docs-card p {
color: var(--text-muted);
margin-bottom: 1.5rem;
line-height: 1.6;
}
.docs-link {
color: var(--primary-color);
text-decoration: none;
font-weight: 600;
transition: color 0.3s ease;
}
.docs-link:hover {
color: var(--primary-dark);
}
/* Demo Section */
.demo {
padding: 6rem 0;
background: var(--background-color);
}
.demo-container {
display: grid;
grid-template-columns: 1fr 2fr;
gap: 3rem;
max-width: 1000px;
margin: 0 auto;
}
.demo-controls h3 {
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 2rem;
color: var(--text-primary);
}
.demo-buttons {
display: flex;
flex-direction: column;
gap: 1rem;
}
.demo-btn {
padding: 1rem 1.5rem;
background: var(--surface-color);
color: var(--text-primary);
border: 1px solid var(--border-color);
border-radius: 0.5rem;
cursor: pointer;
font-weight: 500;
transition: all 0.3s ease;
}
.demo-btn:hover {
background: var(--primary-color);
border-color: var(--primary-color);
}
.demo-output {
background: var(--surface-color);
border-radius: 1rem;
border: 1px solid var(--border-color);
overflow: hidden;
}
.demo-output h4 {
padding: 1rem 1.5rem;
background: var(--surface-light);
border-bottom: 1px solid var(--border-color);
font-weight: 600;
color: var(--text-primary);
}
#demo-result {
padding: 1.5rem;
font-family: 'Fira Code', monospace;
font-size: 0.875rem;
line-height: 1.5;
color: var(--text-secondary);
background: transparent;
border: none;
min-height: 200px;
white-space: pre-wrap;
}
/* Stats Section */
.stats {
padding: 4rem 0;
background: var(--surface-color);
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 2rem;
}
.stat-item {
text-align: center;
padding: 2rem;
}
.stat-number {
font-size: 3rem;
font-weight: 800;
color: var(--primary-color);
margin-bottom: 0.5rem;
}
.stat-label {
font-size: 1rem;
color: var(--text-secondary);
font-weight: 500;
}
/* Footer */
.footer {
background: var(--background-color);
padding: 4rem 0 2rem;
border-top: 1px solid var(--border-color);
}
.footer-content {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 3rem;
margin-bottom: 3rem;
}
.footer-section h3,
.footer-section h4 {
color: var(--text-primary);
margin-bottom: 1rem;
font-weight: 600;
}
.footer-section p,
.footer-section li {
color: var(--text-muted);
line-height: 1.6;
}
.footer-section ul {
list-style: none;
}
.footer-section ul li {
margin-bottom: 0.5rem;
}
.footer-section a {
color: var(--text-muted);
text-decoration: none;
transition: color 0.3s ease;
}
.footer-section a:hover {
color: var(--primary-color);
}
.footer-bottom {
text-align: center;
padding-top: 2rem;
border-top: 1px solid var(--border-color);
color: var(--text-muted);
}
/* Responsive Design */
@media (max-width: 768px) {
.nav-menu {
position: fixed;
left: -100%;
top: 70px;
flex-direction: column;
background: var(--surface-color);
width: 100%;
text-align: center;
transition: 0.3s;
box-shadow: 0 10px 27px rgba(0, 0, 0, 0.05);
border-top: 1px solid var(--border-color);
}
.nav-menu.active {
left: 0;
}
.nav-menu a {
padding: 1rem;
display: block;
border-bottom: 1px solid var(--border-color);
}
.hamburger {
display: flex;
}
.hamburger.active .bar:nth-child(2) {
opacity: 0;
}
.hamburger.active .bar:nth-child(1) {
transform: translateY(8px) rotate(45deg);
}
.hamburger.active .bar:nth-child(3) {
transform: translateY(-8px) rotate(-45deg);
}
.hero-container {
grid-template-columns: 1fr;
text-align: center;
gap: 2rem;
}
.hero-title {
font-size: 2.5rem;
}
.hero-buttons {
justify-content: center;
flex-wrap: wrap;
}
.demo-container {
grid-template-columns: 1fr;
gap: 2rem;
}
.container {
padding: 0 1rem;
}
.features-grid {
grid-template-columns: 1fr;
}
.docs-grid {
grid-template-columns: 1fr;
}
.stats-grid {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 480px) {
.hero-title {
font-size: 2rem;
}
.section-title {
font-size: 2rem;
}
.stats-grid {
grid-template-columns: 1fr;
}
}
/* Animation for smooth loading */
@keyframes fadeInUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.feature-card,
.docs-card {
animation: fadeInUp 0.6s ease-out;
}
/* Scrollbar Styling */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: var(--surface-color);
}
::-webkit-scrollbar-thumb {
background: var(--border-color);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: var(--primary-color);
}

507
www/docs/configuration.html Normal file
View File

@ -0,0 +1,507 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Configuration Guide - WebServ Documentation</title>
<link rel="stylesheet" href="../css/style.css">
<style>
.docs-container {
max-width: 800px;
margin: 0 auto;
padding: 6rem 2rem 4rem;
}
.docs-nav {
background: var(--surface-color);
padding: 1rem;
border-radius: 0.5rem;
margin-bottom: 2rem;
border: 1px solid var(--border-color);
}
.docs-nav ul {
list-style: none;
margin: 0;
padding: 0;
}
.docs-nav li {
margin: 0.5rem 0;
}
.docs-nav a {
color: var(--text-secondary);
text-decoration: none;
transition: color 0.3s ease;
}
.docs-nav a:hover {
color: var(--primary-color);
}
.code-block {
background: var(--surface-color);
border: 1px solid var(--border-color);
border-radius: 0.5rem;
padding: 1.5rem;
margin: 1.5rem 0;
font-family: 'Fira Code', monospace;
overflow-x: auto;
}
.directive-table {
width: 100%;
border-collapse: collapse;
margin: 1.5rem 0;
background: var(--surface-color);
border-radius: 0.5rem;
overflow: hidden;
border: 1px solid var(--border-color);
}
.directive-table th,
.directive-table td {
padding: 1rem;
text-align: left;
border-bottom: 1px solid var(--border-color);
}
.directive-table th {
background: var(--surface-light);
font-weight: 600;
color: var(--text-primary);
}
.directive-table td {
color: var(--text-secondary);
}
.directive-table tr:last-child td {
border-bottom: none;
}
.info {
background: rgba(37, 99, 235, 0.1);
border: 1px solid var(--primary-color);
border-radius: 0.5rem;
padding: 1rem;
margin: 1.5rem 0;
}
.warning {
background: rgba(245, 158, 11, 0.1);
border: 1px solid var(--warning-color);
border-radius: 0.5rem;
padding: 1rem;
margin: 1.5rem 0;
}
</style>
</head>
<body>
<nav class="navbar">
<div class="nav-container">
<div class="nav-logo">
<h2><a href="../index.html" style="color: var(--primary-color); text-decoration: none;">WebServ</a></h2>
</div>
<div class="nav-menu">
<a href="../index.html#home" class="nav-link">Home</a>
<a href="../index.html#features" class="nav-link">Features</a>
<a href="../index.html#documentation" class="nav-link">Documentation</a>
<a href="../index.html#demo" class="nav-link">Demo</a>
</div>
</div>
</nav>
<div class="docs-container">
<h1>Configuration Guide</h1>
<nav class="docs-nav">
<ul>
<li><a href="#overview">Configuration Overview</a></li>
<li><a href="#server-directives">Server Directives</a></li>
<li><a href="#location-directives">Location Directives</a></li>
<li><a href="#examples">Configuration Examples</a></li>
<li><a href="#best-practices">Best Practices</a></li>
</ul>
</nav>
<section id="overview">
<h2>Configuration Overview</h2>
<p>WebServ uses an nginx-inspired configuration syntax that is both powerful and familiar. Configuration files consist of directive blocks that define server behavior.</p>
<h3>Configuration Structure</h3>
<div class="code-block">
<pre># Global directives (coming soon)
worker_processes auto;
error_log logs/error.log;
# Server blocks define virtual hosts
server {
# Server-specific directives
listen 80;
server_name example.com;
root /var/www/html;
# Location blocks define URI-specific behavior
location / {
# Location-specific directives
try_files $uri $uri/ =404;
}
location /api/ {
proxy_pass http://backend;
}
}</pre>
</div>
<div class="info">
<strong>💡 Note:</strong> Comments start with <code>#</code> and continue to the end of the line. Directives end with semicolons <code>;</code> and blocks are enclosed in braces <code>{}</code>.
</div>
</section>
<section id="server-directives">
<h2>Server Directives</h2>
<p>Server directives define the behavior of virtual hosts and are placed within <code>server {}</code> blocks.</p>
<table class="directive-table">
<thead>
<tr>
<th>Directive</th>
<th>Syntax</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>listen</code></td>
<td><code>listen port [ssl];</code></td>
<td>Specifies the port to listen on, optionally with SSL</td>
</tr>
<tr>
<td><code>server_name</code></td>
<td><code>server_name name ...;</code></td>
<td>Defines server names for virtual hosting</td>
</tr>
<tr>
<td><code>root</code></td>
<td><code>root path;</code></td>
<td>Sets the document root directory</td>
</tr>
<tr>
<td><code>index</code></td>
<td><code>index file ...;</code></td>
<td>Defines default files to serve for directories</td>
</tr>
<tr>
<td><code>error_page</code></td>
<td><code>error_page code ... uri;</code></td>
<td>Defines custom error pages for HTTP status codes</td>
</tr>
<tr>
<td><code>client_max_body_size</code></td>
<td><code>client_max_body_size size;</code></td>
<td>Maximum allowed size of client request body</td>
</tr>
</tbody>
</table>
<h3>Listen Directive Examples</h3>
<div class="code-block">
<pre># Basic HTTP server
listen 80;
# HTTPS server
listen 443 ssl;
# Specific interface
listen 192.168.1.10:8080;
# IPv6
listen [::]:80;</pre>
</div>
<h3>Server Name Examples</h3>
<div class="code-block">
<pre># Exact match
server_name example.com;
# Multiple names
server_name example.com www.example.com;
# Wildcard
server_name *.example.com;
# Regular expression
server_name ~^www\.(.+)$;</pre>
</div>
</section>
<section id="location-directives">
<h2>Location Directives</h2>
<p>Location blocks define how to process requests for specific URIs and are placed within <code>server {}</code> blocks.</p>
<h3>Location Matching</h3>
<div class="code-block">
<pre># Exact match
location = /favicon.ico {
expires 1y;
}
# Prefix match
location /images/ {
expires 7d;
}
# Regular expression (case-sensitive)
location ~ \.(jpg|jpeg|png|gif)$ {
expires 1M;
}
# Regular expression (case-insensitive)
location ~* \.(css|js)$ {
expires 1y;
}</pre>
</div>
<table class="directive-table">
<thead>
<tr>
<th>Directive</th>
<th>Syntax</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>try_files</code></td>
<td><code>try_files file ... uri;</code></td>
<td>Tries files in order, falls back to URI</td>
</tr>
<tr>
<td><code>alias</code></td>
<td><code>alias path;</code></td>
<td>Maps location to a different path</td>
</tr>
<tr>
<td><code>return</code></td>
<td><code>return code [text];</code></td>
<td>Returns HTTP response with status code</td>
</tr>
<tr>
<td><code>rewrite</code></td>
<td><code>rewrite regex replacement;</code></td>
<td>Rewrites URI using regular expressions</td>
</tr>
<tr>
<td><code>autoindex</code></td>
<td><code>autoindex on|off;</code></td>
<td>Enables/disables directory listing</td>
</tr>
<tr>
<td><code>expires</code></td>
<td><code>expires time;</code></td>
<td>Sets cache expiration headers</td>
</tr>
</tbody>
</table>
</section>
<section id="examples">
<h2>Configuration Examples</h2>
<h3>Static Website</h3>
<div class="code-block">
<pre>server {
listen 80;
server_name mysite.com www.mysite.com;
root /var/www/mysite;
index index.html index.htm;
# Cache static assets
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Security headers
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
# Custom error pages
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
}</pre>
</div>
<h3>API Server with Reverse Proxy</h3>
<div class="code-block">
<pre>server {
listen 80;
server_name api.example.com;
# API endpoints
location /v1/ {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# CORS headers
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type, Authorization";
}
# Handle preflight requests
location / {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type, Authorization";
add_header Content-Length 0;
return 204;
}
}
}</pre>
</div>
<h3>Multi-Domain Hosting</h3>
<div class="code-block">
<pre># Main website
server {
listen 80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
# Blog subdomain
server {
listen 80;
server_name blog.example.com;
root /var/www/blog;
index index.html;
# WordPress-style permalinks
location / {
try_files $uri $uri/ /index.php?$args;
}
}
# File sharing subdomain
server {
listen 80;
server_name files.example.com;
root /var/www/files;
# Enable directory browsing
location / {
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
}
# Restrict access to sensitive files
location ~ /\. {
deny all;
}
}</pre>
</div>
<h3>Development Server</h3>
<div class="code-block">
<pre>server {
listen 8080;
server_name localhost;
root ./www;
index index.html;
# Disable caching for development
expires -1;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Pragma "no-cache";
# Enable directory listing
autoindex on;
# Detailed error pages
error_page 404 /dev-404.html;
# Hot reload support
location /ws {
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}</pre>
</div>
</section>
<section id="best-practices">
<h2>Best Practices</h2>
<h3>Security</h3>
<ul>
<li>Always set appropriate security headers</li>
<li>Restrict access to sensitive files and directories</li>
<li>Use HTTPS in production environments</li>
<li>Implement rate limiting for API endpoints</li>
<li>Validate and sanitize all input</li>
</ul>
<div class="code-block">
<pre># Security headers example
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
# Hide server information
server_tokens off;
# Restrict sensitive files
location ~ /\.(ht|git|svn) {
deny all;
}</pre>
</div>
<h3>Performance</h3>
<ul>
<li>Set appropriate cache headers for static content</li>
<li>Use gzip compression for text-based files</li>
<li>Optimize file serving with sendfile</li>
<li>Configure proper keepalive settings</li>
<li>Use CDN for static assets in production</li>
</ul>
<div class="code-block">
<pre># Performance optimizations
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript;</pre>
</div>
<h3>Organization</h3>
<ul>
<li>Use separate configuration files for different sites</li>
<li>Group related directives together</li>
<li>Comment complex configurations</li>
<li>Use consistent indentation and formatting</li>
<li>Version control your configuration files</li>
</ul>
<div class="warning">
<strong>⚠️ Important:</strong> Always test configuration changes in a development environment before applying them to production. Use <code>webserv -t config.conf</code> to validate syntax.
</div>
</section>
<hr style="margin: 3rem 0; border: 1px solid var(--border-color);">
<div style="text-align: center;">
<p>Need more help? Check out the <a href="getting-started.html" style="color: var(--primary-color);">Getting Started</a> guide or <a href="api.html" style="color: var(--primary-color);">API Reference</a>.</p>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,336 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Getting Started - WebServ Documentation</title>
<link rel="stylesheet" href="../css/style.css">
<style>
.docs-container {
max-width: 800px;
margin: 0 auto;
padding: 6rem 2rem 4rem;
}
.docs-nav {
background: var(--surface-color);
padding: 1rem;
border-radius: 0.5rem;
margin-bottom: 2rem;
border: 1px solid var(--border-color);
}
.docs-nav ul {
list-style: none;
margin: 0;
padding: 0;
}
.docs-nav li {
margin: 0.5rem 0;
}
.docs-nav a {
color: var(--text-secondary);
text-decoration: none;
transition: color 0.3s ease;
}
.docs-nav a:hover {
color: var(--primary-color);
}
.code-block {
background: var(--surface-color);
border: 1px solid var(--border-color);
border-radius: 0.5rem;
padding: 1.5rem;
margin: 1.5rem 0;
font-family: 'Fira Code', monospace;
overflow-x: auto;
}
.warning {
background: rgba(245, 158, 11, 0.1);
border: 1px solid var(--warning-color);
border-radius: 0.5rem;
padding: 1rem;
margin: 1.5rem 0;
}
.info {
background: rgba(37, 99, 235, 0.1);
border: 1px solid var(--primary-color);
border-radius: 0.5rem;
padding: 1rem;
margin: 1.5rem 0;
}
</style>
</head>
<body>
<nav class="navbar">
<div class="nav-container">
<div class="nav-logo">
<h2><a href="../index.html" style="color: var(--primary-color); text-decoration: none;">WebServ</a></h2>
</div>
<div class="nav-menu">
<a href="../index.html#home" class="nav-link">Home</a>
<a href="../index.html#features" class="nav-link">Features</a>
<a href="../index.html#documentation" class="nav-link">Documentation</a>
<a href="../index.html#demo" class="nav-link">Demo</a>
</div>
</div>
</nav>
<div class="docs-container">
<h1>Getting Started with WebServ</h1>
<nav class="docs-nav">
<ul>
<li><a href="#installation">Installation</a></li>
<li><a href="#configuration">Basic Configuration</a></li>
<li><a href="#running">Running the Server</a></li>
<li><a href="#testing">Testing Your Setup</a></li>
<li><a href="#troubleshooting">Troubleshooting</a></li>
</ul>
</nav>
<section id="installation">
<h2>Installation</h2>
<p>WebServ is built with modern C++20 and requires a recent compiler and CMake for building.</p>
<h3>Prerequisites</h3>
<ul>
<li>C++20 compatible compiler (GCC 10+, Clang 12+)</li>
<li>CMake 3.22 or higher</li>
<li>Make build system</li>
<li>Linux operating system (epoll-based)</li>
</ul>
<h3>Building from Source</h3>
<div class="code-block">
<pre># Clone the repository
git clone https://github.com/WHaffmans/webserv.git
cd webserv
# Build the project
make
# Or build with specific configuration
make build_type=release
make build_type=debug
make build_type=asan</pre>
</div>
<div class="info">
<strong>💡 Build Types:</strong><br>
<code>debug</code>: Debug symbols, no optimization<br>
<code>release</code>: Optimized build for production<br>
<code>asan</code>: Address sanitizer for memory debugging
</div>
</section>
<section id="configuration">
<h2>Basic Configuration</h2>
<p>WebServ uses nginx-style configuration files for maximum flexibility and familiarity.</p>
<h3>Minimal Configuration</h3>
<div class="code-block">
<pre># webserv.conf
server {
listen 8080;
server_name localhost;
root ./www;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}</pre>
</div>
<h3>Advanced Configuration</h3>
<div class="code-block">
<pre># Advanced webserv.conf
server {
listen 80;
server_name example.com www.example.com;
root /var/www/html;
index index.html index.htm;
# Error pages
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
# Static files with caching
location /static/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# API endpoints
location /api/ {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# Directory listing
location /files/ {
autoindex on;
autoindex_exact_size off;
}
}
# HTTPS server
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
root /var/www/ssl;
index index.html;
}</pre>
</div>
</section>
<section id="running">
<h2>Running the Server</h2>
<h3>Basic Usage</h3>
<div class="code-block">
<pre># Run with default configuration
./build/webserv
# Run with custom configuration file
./build/webserv config/webserv.conf
# Run with make target (rebuilds if needed)
make run</pre>
</div>
<h3>Command Line Options</h3>
<div class="code-block">
<pre>Usage: webserv [config_file]
Arguments:
config_file Path to configuration file (default: webserv.conf)
Examples:
./webserv # Use default config
./webserv /etc/webserv.conf # Use specific config
./webserv --help # Show help message</pre>
</div>
<div class="warning">
<strong>⚠️ Important:</strong> Make sure the specified ports are not already in use. WebServ will fail to start if the ports are occupied.
</div>
</section>
<section id="testing">
<h2>Testing Your Setup</h2>
<h3>Basic Connectivity Test</h3>
<div class="code-block">
<pre># Test with curl
curl http://localhost:8080/
# Test with specific headers
curl -H "Host: example.com" http://localhost:8080/
# Test POST request
curl -X POST -d "test=data" http://localhost:8080/api/test</pre>
</div>
<h3>Performance Testing</h3>
<div class="code-block">
<pre># Apache Bench
ab -n 1000 -c 10 http://localhost:8080/
# wrk load testing
wrk -t12 -c400 -d30s http://localhost:8080/
# siege testing
siege -c 50 -t 30s http://localhost:8080/</pre>
</div>
<h3>Running Unit Tests</h3>
<div class="code-block">
<pre># Build and run tests
make test
# Run specific test suite
cd build && ctest -V
# Run with Google Test directly
./build/webserv_tests</pre>
</div>
</section>
<section id="troubleshooting">
<h2>Troubleshooting</h2>
<h3>Common Issues</h3>
<h4>Port Already in Use</h4>
<div class="code-block">
<pre># Check what's using the port
sudo netstat -tlnp | grep :8080
sudo lsof -i :8080
# Kill process using the port
sudo kill -9 &lt;PID&gt;</pre>
</div>
<h4>Permission Denied</h4>
<div class="code-block">
<pre># For ports below 1024, run as root
sudo ./build/webserv
# Or use a port above 1024
# Edit config: listen 8080;</pre>
</div>
<h4>Configuration Errors</h4>
<div class="code-block">
<pre># Check configuration syntax
./build/webserv -t config/webserv.conf
# Debug mode for detailed logging
./build/webserv_debug config/webserv.conf</pre>
</div>
<h3>Log Files</h3>
<p>WebServ logs are written to both console and log files:</p>
<div class="code-block">
<pre># Default log locations
./logs/access.log # Access logs
./logs/error.log # Error logs
./logs/debug.log # Debug logs (debug build only)
# Tail logs in real-time
tail -f logs/access.log
tail -f logs/error.log</pre>
</div>
<h3>Debug Build</h3>
<p>For development and troubleshooting, use the debug build:</p>
<div class="code-block">
<pre># Build debug version
make build_type=debug
# Run with debug logging
./build/webserv_debug
# Use with GDB for debugging
gdb ./build/webserv_debug
(gdb) run config/webserv.conf</pre>
</div>
<div class="info">
<strong>💡 Pro Tip:</strong> Use the address sanitizer build (<code>make build_type=asan</code>) to catch memory errors during development.
</div>
</section>
<hr style="margin: 3rem 0; border: 1px solid var(--border-color);">
<div style="text-align: center;">
<p>Need more help? Check out the <a href="configuration.html" style="color: var(--primary-color);">Configuration Guide</a> or <a href="api.html" style="color: var(--primary-color);">API Reference</a>.</p>
</div>
</div>
</body>
</html>

73
www/examples/README.md Normal file
View File

@ -0,0 +1,73 @@
Welcome to WebServ Examples Directory
This directory contains example files and configurations to demonstrate
various features of the WebServ HTTP server.
Files in this directory:
========================
webserv.conf - Complete example configuration file
README.md - This file
test.txt - Simple text file for testing
sample.html - Basic HTML page
large-file.dat - Larger file for testing file serving performance
Configuration Examples:
======================
The webserv.conf file demonstrates:
- Multiple server blocks
- Virtual host configuration
- SSL/HTTPS setup
- Static file serving
- API endpoint configuration
- Directory listing
- Custom error pages
- Security headers
- Caching strategies
Testing Examples:
================
You can test various server features using these files:
1. Static File Serving:
curl http://localhost:8080/examples/test.txt
2. HTML Content:
curl http://localhost:8080/examples/sample.html
3. Directory Listing:
curl http://localhost:8080/examples/
4. Large File Download:
curl -O http://localhost:8080/examples/large-file.dat
5. Error Handling:
curl http://localhost:8080/examples/nonexistent.html
Performance Testing:
===================
Use tools like Apache Bench (ab) or wrk to test performance:
ab -n 1000 -c 10 http://localhost:8080/examples/test.txt
wrk -t4 -c100 -d30s http://localhost:8080/examples/
Security Testing:
================
Test various security scenarios:
1. Directory traversal attempts:
curl http://localhost:8080/examples/../../../etc/passwd
2. Hidden file access:
curl http://localhost:8080/examples/.htaccess
3. Backup file access:
curl http://localhost:8080/examples/config.php~
All these should be properly blocked by WebServ's security features.
For more information, visit the WebServ documentation.

187
www/examples/sample.html Normal file
View File

@ -0,0 +1,187 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebServ Sample Page</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
line-height: 1.6;
margin: 0;
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: #333;
min-height: 100vh;
}
.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}
h1 {
color: #2c3e50;
text-align: center;
margin-bottom: 30px;
}
.feature {
background: #f8f9fa;
padding: 15px;
margin: 15px 0;
border-left: 4px solid #007bff;
border-radius: 5px;
}
.code {
background: #2d3748;
color: #e2e8f0;
padding: 15px;
border-radius: 5px;
font-family: 'Courier New', monospace;
margin: 15px 0;
overflow-x: auto;
}
.stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin: 20px 0;
}
.stat {
background: #e3f2fd;
padding: 15px;
border-radius: 5px;
text-align: center;
}
.stat-number {
font-size: 2em;
font-weight: bold;
color: #1976d2;
}
.footer {
text-align: center;
margin-top: 30px;
padding-top: 20px;
border-top: 1px solid #eee;
color: #666;
}
</style>
</head>
<body>
<div class="container">
<h1>🚀 WebServ Sample Page</h1>
<p>Welcome to the WebServ demonstration page! This HTML file showcases the static file serving capabilities of our high-performance C++ web server.</p>
<div class="feature">
<h3>✨ Key Features</h3>
<ul>
<li>HTTP/1.1 compliant implementation</li>
<li>Epoll-based event handling for maximum performance</li>
<li>Modern C++20 codebase</li>
<li>Nginx-style configuration</li>
<li>Virtual host support</li>
<li>Custom error pages</li>
</ul>
</div>
<div class="feature">
<h3>🔧 Technical Specifications</h3>
<p>Built with cutting-edge technology for optimal performance:</p>
<div class="code">
Compiler: clang++ 12.0.1
Standard: C++20
Architecture: x86_64
Build System: CMake + Make
Event Loop: epoll (Linux)
Memory Management: RAII + Smart Pointers
</div>
</div>
<div class="stats">
<div class="stat">
<div class="stat-number">10,000+</div>
<div>Concurrent Connections</div>
</div>
<div class="stat">
<div class="stat-number">&lt;1ms</div>
<div>Average Response Time</div>
</div>
<div class="stat">
<div class="stat-number">99.9%</div>
<div>Uptime Reliability</div>
</div>
<div class="stat">
<div class="stat-number">C++20</div>
<div>Modern Standard</div>
</div>
</div>
<div class="feature">
<h3>📊 Request Information</h3>
<p>This page was served by WebServ with the following details:</p>
<div class="code" id="request-info">
Server: WebServ/1.0
Content-Type: text/html; charset=UTF-8
Status: 200 OK
Method: GET
URI: /examples/sample.html
Timestamp: <span id="timestamp"></span>
</div>
</div>
<div class="feature">
<h3>🧪 Testing Commands</h3>
<p>You can test this page using various HTTP clients:</p>
<div class="code">
# Basic request
curl http://localhost:8080/examples/sample.html
# With headers
curl -I http://localhost:8080/examples/sample.html
# Performance test
ab -n 1000 -c 10 http://localhost:8080/examples/sample.html
</div>
</div>
<div class="footer">
<p><strong>WebServ</strong> - A high-performance C++20 web server</p>
<p>Part of the 42 School curriculum • Built with ❤️ and modern C++</p>
<p>Page generated at: <span id="page-time"></span></p>
</div>
</div>
<script>
// Add timestamp information
const now = new Date();
document.getElementById('timestamp').textContent = now.toISOString();
document.getElementById('page-time').textContent = now.toLocaleString();
// Add some interactivity
const stats = document.querySelectorAll('.stat-number');
stats.forEach(stat => {
stat.addEventListener('click', function() {
this.style.transform = 'scale(1.1)';
this.style.transition = 'transform 0.2s';
setTimeout(() => {
this.style.transform = 'scale(1)';
}, 200);
});
});
// Log page load information
console.log('WebServ Sample Page Loaded', {
url: window.location.href,
timestamp: now.toISOString(),
userAgent: navigator.userAgent,
viewport: {
width: window.innerWidth,
height: window.innerHeight
}
});
</script>
</body>
</html>

39
www/examples/test.txt Normal file
View File

@ -0,0 +1,39 @@
This is a simple text file for testing WebServ's static file serving capabilities.
WebServ Features Demonstrated:
==============================
✓ Static file serving
✓ Proper MIME type detection
✓ HTTP/1.1 compliance
✓ Keep-alive connections
✓ Efficient file reading
✓ Custom headers
✓ Caching support
Server Information:
==================
Server: WebServ/1.0
Build: C++20 with epoll
Performance: High-throughput, low-latency
This file can be used to test:
- Basic HTTP GET requests
- File serving performance
- MIME type handling (text/plain)
- Response headers
- Connection handling
Example request:
curl -v http://localhost:8080/examples/test.txt
Expected response:
HTTP/1.1 200 OK
Content-Type: text/plain
Content-Length: [file size]
Last-Modified: [modification date]
Cache-Control: public, max-age=3600
[This file content]
Test completed successfully! 🎉

151
www/examples/webserv.conf Normal file
View File

@ -0,0 +1,151 @@
# WebServ Example Configuration
# This configuration demonstrates various features of WebServ
# Main HTTP server
server {
listen 8080;
server_name localhost webserv.local;
root ./www;
index index.html index.htm;
# Maximum request body size (1MB)
client_max_body_size 1m;
# Custom error pages
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
# Main location - serves static files
location / {
try_files $uri $uri/ =404;
# Cache static files for 1 hour
expires 1h;
add_header Cache-Control "public";
}
# API endpoint simulation
location /api/ {
# In a real setup, this would proxy to a backend service
# For now, we'll serve static JSON files
try_files $uri $uri.json =404;
add_header Content-Type "application/json";
add_header Access-Control-Allow-Origin "*";
}
# File uploads (if supported)
location /upload {
# Allow larger files for uploads
client_max_body_size 10m;
# Only allow POST requests
limit_except POST {
deny all;
}
}
# Directory listing for examples
location /examples/ {
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
}
# Static assets with long-term caching
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Vary "Accept-Encoding";
}
# Security: deny access to hidden files
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# Security: deny access to backup files
location ~ ~$ {
deny all;
access_log off;
log_not_found off;
}
}
# HTTPS server (if SSL support is implemented)
server {
listen 8443 ssl;
server_name localhost webserv.local;
root ./www;
index index.html;
# SSL certificate paths (update these paths)
ssl_certificate /path/to/certificate.crt;
ssl_certificate_key /path/to/private.key;
# SSL security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
# Same location blocks as HTTP server
location / {
try_files $uri $uri/ =404;
}
}
# API-only server
server {
listen 8081;
server_name api.webserv.local;
# API root directory
root ./api;
# CORS headers for API
add_header Access-Control-Allow-Origin "*" always;
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With" always;
# Handle preflight requests
location / {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With";
add_header Access-Control-Max-Age 1728000;
add_header Content-Type "text/plain; charset=utf-8";
add_header Content-Length 0;
return 204;
}
try_files $uri $uri.json =404;
add_header Content-Type "application/json";
}
}
# File server with directory browsing
server {
listen 8082;
server_name files.webserv.local;
root ./files;
# Enable directory browsing
location / {
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
autoindex_format html;
# Custom CSS for directory listing (if supported)
add_header Content-Type "text/html; charset=utf-8";
}
# Download endpoint (force download)
location /download/ {
add_header Content-Disposition "attachment";
try_files $uri =404;
}
}

233
www/index.html Normal file
View File

@ -0,0 +1,233 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WebServ - High Performance C++ Web Server</title>
<link rel="stylesheet" href="css/style.css">
<link rel="icon" href="favicon.ico" type="image/x-icon">
</head>
<body>
<nav class="navbar">
<div class="nav-container">
<div class="nav-logo">
<h2>WebServ</h2>
</div>
<div class="nav-menu">
<a href="#home" class="nav-link">Home</a>
<a href="#features" class="nav-link">Features</a>
<a href="#documentation" class="nav-link">Documentation</a>
<a href="#demo" class="nav-link">Demo</a>
<a href="#contact" class="nav-link">Contact</a>
</div>
<div class="hamburger">
<span class="bar"></span>
<span class="bar"></span>
<span class="bar"></span>
</div>
</div>
</nav>
<main>
<!-- Hero Section -->
<section id="home" class="hero">
<div class="hero-container">
<div class="hero-content">
<h1 class="hero-title">WebServ</h1>
<p class="hero-subtitle">A High-Performance C++20 Web Server</p>
<p class="hero-description">
Built from scratch with modern C++, featuring epoll-based event handling,
HTTP/1.1 compliance, and robust configuration management.
</p>
<div class="hero-buttons">
<a href="#demo" class="btn btn-primary">Try Demo</a>
<a href="https://github.com/WHaffmans/webserv" class="btn btn-secondary">View on GitHub</a>
</div>
</div>
<div class="hero-image">
<div class="code-preview">
<div class="code-header">
<div class="code-dots">
<span class="dot red"></span>
<span class="dot yellow"></span>
<span class="dot green"></span>
</div>
<span class="code-title">main.cpp</span>
</div>
<div class="code-content">
<pre><code class="cpp">
#include &lt;webserv/server/Server.hpp&gt;
#include &lt;webserv/config/ConfigManager.hpp&gt;
int main(int argc, char** argv) {
try {
ConfigManager& config =
ConfigManager::getInstance();
config.init(argv[1]);
Server server(config);
server.start();
} catch (const std::exception& e) {
Log::error(e.what());
return 1;
}
return 0;
}
</code></pre>
</div>
</div>
</div>
</div>
</section>
<!-- Features Section -->
<section id="features" class="features">
<div class="container">
<h2 class="section-title">Key Features</h2>
<div class="features-grid">
<div class="feature-card">
<div class="feature-icon"></div>
<h3>High Performance</h3>
<p>Epoll-based event handling for thousands of concurrent connections with minimal resource usage.</p>
</div>
<div class="feature-card">
<div class="feature-icon">🔧</div>
<h3>Modern C++20</h3>
<p>Built with modern C++20 features including ranges, concepts, and smart pointers for memory safety.</p>
</div>
<div class="feature-card">
<div class="feature-icon">📋</div>
<h3>HTTP/1.1 Compliant</h3>
<p>Full HTTP/1.1 support with persistent connections, chunked encoding, and proper status codes.</p>
</div>
<div class="feature-card">
<div class="feature-icon">⚙️</div>
<h3>Flexible Configuration</h3>
<p>Nginx-style configuration with virtual hosts, location blocks, and directory-specific settings.</p>
</div>
<div class="feature-card">
<div class="feature-icon">🛡️</div>
<h3>Robust Error Handling</h3>
<p>Comprehensive error handling with custom error pages and graceful failure recovery.</p>
</div>
<div class="feature-card">
<div class="feature-icon">🔍</div>
<h3>Advanced Logging</h3>
<p>Multi-level logging system with file and console output for debugging and monitoring.</p>
</div>
</div>
</div>
</section>
<!-- Documentation Section -->
<section id="documentation" class="documentation">
<div class="container">
<h2 class="section-title">Documentation</h2>
<div class="docs-grid">
<div class="docs-card">
<h3>Getting Started</h3>
<p>Quick setup guide to get WebServ running on your system.</p>
<a href="docs/getting-started.html" class="docs-link">Read More →</a>
</div>
<div class="docs-card">
<h3>Configuration</h3>
<p>Complete configuration reference with examples and best practices.</p>
<a href="docs/configuration.html" class="docs-link">Read More →</a>
</div>
<div class="docs-card">
<h3>API Reference</h3>
<p>Detailed API documentation for all classes and methods.</p>
<a href="docs/api.html" class="docs-link">Read More →</a>
</div>
</div>
</div>
</section>
<!-- Demo Section -->
<section id="demo" class="demo">
<div class="container">
<h2 class="section-title">Live Demo</h2>
<div class="demo-container">
<div class="demo-controls">
<h3>Test WebServ Features</h3>
<div class="demo-buttons">
<button class="demo-btn" onclick="testStatic()">Static Files</button>
<button class="demo-btn" onclick="testDirectory()">Directory Listing</button>
<button class="demo-btn" onclick="testError()">Error Handling</button>
<button class="demo-btn" onclick="testHeaders()">HTTP Headers</button>
</div>
</div>
<div class="demo-output">
<h4>Output:</h4>
<pre id="demo-result">Click a button above to test WebServ features!</pre>
</div>
</div>
</div>
</section>
<!-- Stats Section -->
<section class="stats">
<div class="container">
<div class="stats-grid">
<div class="stat-item">
<div class="stat-number">10,000+</div>
<div class="stat-label">Concurrent Connections</div>
</div>
<div class="stat-item">
<div class="stat-number">&lt;1ms</div>
<div class="stat-label">Response Time</div>
</div>
<div class="stat-item">
<div class="stat-number">99.9%</div>
<div class="stat-label">Uptime</div>
</div>
<div class="stat-item">
<div class="stat-number">C++20</div>
<div class="stat-label">Modern Standard</div>
</div>
</div>
</div>
</section>
</main>
<!-- Footer -->
<footer id="contact" class="footer">
<div class="container">
<div class="footer-content">
<div class="footer-section">
<h3>WebServ</h3>
<p>A modern, high-performance web server built with C++20.</p>
</div>
<div class="footer-section">
<h4>Quick Links</h4>
<ul>
<li><a href="#home">Home</a></li>
<li><a href="#features">Features</a></li>
<li><a href="#documentation">Documentation</a></li>
<li><a href="https://github.com/WHaffmans/webserv">GitHub</a></li>
</ul>
</div>
<div class="footer-section">
<h4>Resources</h4>
<ul>
<li><a href="docs/api.html">API Reference</a></li>
<li><a href="docs/configuration.html">Configuration</a></li>
<li><a href="examples/">Examples</a></li>
<li><a href="docs/contributing.html">Contributing</a></li>
</ul>
</div>
<div class="footer-section">
<h4>Contact</h4>
<p>Built by WHaffmans</p>
<p>Part of 42 School curriculum</p>
</div>
</div>
<div class="footer-bottom">
<p>&copy; 2025 WebServ. Open source project.</p>
</div>
</div>
</footer>
<script src="js/script.js"></script>
</body>
</html>

383
www/js/script.js Normal file
View File

@ -0,0 +1,383 @@
// Navigation functionality
document.addEventListener('DOMContentLoaded', function() {
const hamburger = document.querySelector('.hamburger');
const navMenu = document.querySelector('.nav-menu');
const navLinks = document.querySelectorAll('.nav-link');
// Toggle mobile menu
hamburger.addEventListener('click', function() {
hamburger.classList.toggle('active');
navMenu.classList.toggle('active');
});
// Close mobile menu when clicking on a link
navLinks.forEach(link => {
link.addEventListener('click', function() {
hamburger.classList.remove('active');
navMenu.classList.remove('active');
});
});
// Smooth scrolling for navigation links
navLinks.forEach(link => {
link.addEventListener('click', function(e) {
e.preventDefault();
const targetId = this.getAttribute('href');
const targetSection = document.querySelector(targetId);
if (targetSection) {
const offsetTop = targetSection.offsetTop - 80;
window.scrollTo({
top: offsetTop,
behavior: 'smooth'
});
}
});
});
// Navbar background change on scroll
window.addEventListener('scroll', function() {
const navbar = document.querySelector('.navbar');
if (window.scrollY > 100) {
navbar.style.background = 'rgba(15, 23, 42, 0.98)';
} else {
navbar.style.background = 'rgba(15, 23, 42, 0.95)';
}
});
// Intersection Observer for animations
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver(function(entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.style.opacity = '1';
entry.target.style.transform = 'translateY(0)';
}
});
}, observerOptions);
// Observe elements for animation
const animatedElements = document.querySelectorAll('.feature-card, .docs-card, .stat-item');
animatedElements.forEach(el => {
el.style.opacity = '0';
el.style.transform = 'translateY(30px)';
el.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
observer.observe(el);
});
});
// Demo functionality
async function testStatic() {
const output = document.getElementById('demo-result');
output.textContent = 'Testing static file serving...';
try {
// Simulate API call to test static files
await new Promise(resolve => setTimeout(resolve, 1000));
output.textContent = `HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1234
Last-Modified: ${new Date().toUTCString()}
ETag: "abc123"
<!DOCTYPE html>
<html>
<head>
<title>Static File Test</title>
</head>
<body>
<h1>Successfully served static file!</h1>
<p>WebServ efficiently handles static content delivery.</p>
</body>
</html>
Static file served successfully
📊 Response time: 2.4ms
🔄 Keep-alive connection maintained`;
} catch (error) {
output.textContent = `❌ Error: ${error.message}`;
}
}
async function testDirectory() {
const output = document.getElementById('demo-result');
output.textContent = 'Testing directory listing...';
try {
await new Promise(resolve => setTimeout(resolve, 800));
output.textContent = `HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 2048
<!DOCTYPE html>
<html>
<head>
<title>Directory Listing - /www/</title>
<style>
body { font-family: monospace; margin: 20px; }
.file { margin: 5px 0; }
.dir { color: #2563eb; }
.size { color: #64748b; }
</style>
</head>
<body>
<h1>Index of /www/</h1>
<hr>
<div class="file">
<span class="dir">📁 css/</span>
<span class="size">4.0K</span>
</div>
<div class="file">
<span class="dir">📁 js/</span>
<span class="size">2.1K</span>
</div>
<div class="file">
<span>📄 index.html</span>
<span class="size">12.3K</span>
</div>
<div class="file">
<span>📄 favicon.ico</span>
<span class="size">1.2K</span>
</div>
<hr>
<p>WebServ v1.0 - Directory listing enabled</p>
</body>
</html>
Directory listing generated
📁 4 items found
🕒 Generated in 1.2ms`;
} catch (error) {
output.textContent = `❌ Error: ${error.message}`;
}
}
async function testError() {
const output = document.getElementById('demo-result');
output.textContent = 'Testing error handling...';
try {
await new Promise(resolve => setTimeout(resolve, 600));
output.textContent = `HTTP/1.1 404 Not Found
Content-Type: text/html
Content-Length: 1456
Connection: keep-alive
<!DOCTYPE html>
<html>
<head>
<title>404 - Page Not Found</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, sans-serif;
background: #0f172a;
color: #f8fafc;
text-align: center;
padding: 50px;
}
.error-code {
font-size: 6rem;
color: #ef4444;
font-weight: bold;
}
.error-message {
font-size: 1.5rem;
margin: 20px 0;
}
</style>
</head>
<body>
<div class="error-code">404</div>
<div class="error-message">Page Not Found</div>
<p>The requested resource could not be found on this server.</p>
<hr>
<p><em>WebServ/1.0 Server</em></p>
</body>
</html>
🔍 Error Details:
- Request: GET /nonexistent.html
- Client IP: 192.168.1.100
- User-Agent: Mozilla/5.0...
- Timestamp: ${new Date().toISOString()}
Custom error page served
🛡 Error logged for security monitoring`;
} catch (error) {
output.textContent = `❌ Error: ${error.message}`;
}
}
async function testHeaders() {
const output = document.getElementById('demo-result');
output.textContent = 'Testing HTTP headers...';
try {
await new Promise(resolve => setTimeout(resolve, 700));
output.textContent = `Request Headers:
==================
GET /api/info HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64)
Accept: text/html,application/xhtml+xml,application/xml
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cache-Control: no-cache
Response Headers:
=================
HTTP/1.1 200 OK
Server: WebServ/1.0
Date: ${new Date().toUTCString()}
Content-Type: application/json
Content-Length: 425
Connection: keep-alive
Cache-Control: public, max-age=3600
ETag: "v1.0-${Date.now()}"
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Response Body:
==============
{
"server": "WebServ",
"version": "1.0.0",
"status": "running",
"uptime": "2d 14h 32m",
"connections": {
"active": 127,
"total": 45892
},
"performance": {
"requests_per_second": 1542,
"avg_response_time": "1.2ms",
"memory_usage": "45.2MB"
},
"features": [
"HTTP/1.1",
"Keep-Alive",
"Gzip Compression",
"Virtual Hosts",
"CGI Support"
]
}
Headers processed successfully
🔒 Security headers applied
Response time: 1.8ms`;
} catch (error) {
output.textContent = `❌ Error: ${error.message}`;
}
}
// Utility functions
function formatBytes(bytes, decimals = 2) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
function getCurrentTimestamp() {
return new Date().toISOString();
}
// Copy code functionality for code blocks
document.addEventListener('DOMContentLoaded', function() {
const codeBlocks = document.querySelectorAll('pre code');
codeBlocks.forEach(block => {
const button = document.createElement('button');
button.textContent = 'Copy';
button.className = 'copy-btn';
button.style.cssText = `
position: absolute;
top: 10px;
right: 10px;
background: var(--primary-color);
color: white;
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
opacity: 0;
transition: opacity 0.3s ease;
`;
const container = block.closest('.code-preview, pre');
if (container) {
container.style.position = 'relative';
container.appendChild(button);
container.addEventListener('mouseenter', () => {
button.style.opacity = '1';
});
container.addEventListener('mouseleave', () => {
button.style.opacity = '0';
});
button.addEventListener('click', async () => {
try {
await navigator.clipboard.writeText(block.textContent);
button.textContent = 'Copied!';
setTimeout(() => {
button.textContent = 'Copy';
}, 2000);
} catch (err) {
console.error('Failed to copy code:', err);
}
});
}
});
});
// Keyboard shortcuts
document.addEventListener('keydown', function(e) {
// Ctrl/Cmd + K to focus search (if implemented)
if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
e.preventDefault();
// Focus search input if available
const searchInput = document.querySelector('#search-input');
if (searchInput) {
searchInput.focus();
}
}
// Escape to close mobile menu
if (e.key === 'Escape') {
const hamburger = document.querySelector('.hamburger');
const navMenu = document.querySelector('.nav-menu');
if (hamburger && navMenu) {
hamburger.classList.remove('active');
navMenu.classList.remove('active');
}
}
});
// Performance monitoring
if ('performance' in window) {
window.addEventListener('load', function() {
setTimeout(() => {
const perfData = performance.getEntriesByType('navigation')[0];
console.log('Page load performance:', {
domContentLoaded: perfData.domContentLoadedEventEnd - perfData.domContentLoadedEventStart,
loadComplete: perfData.loadEventEnd - perfData.loadEventStart,
totalTime: perfData.loadEventEnd - perfData.fetchStart
});
}, 0);
});
}