-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
236 lines (218 loc) Β· 22 KB
/
index.html
File metadata and controls
236 lines (218 loc) Β· 22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Titan - HTTP Server</title>
<link rel="icon" type="image/x-icon" href="/favicon_io/favicon.ico">
<link rel="icon" type="image/png" sizes="32x32" href="/favicon_io/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/favicon_io/favicon-16x16.png">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
body { font-family: 'JetBrains Mono', 'Courier New', 'Monaco', monospace; }
code, .font-mono { font-family: 'JetBrains Mono', monospace; }
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.loading {
animation: spin 1s linear infinite;
}
</style>
</head>
<body class="bg-gray-900 text-gray-100">
<div class="max-w-6xl mx-auto p-5">
<!-- Hero Section -->
<div class="text-center bg-gray-800 border-b-2 border-gray-700 py-12 px-6 mb-8 rounded-lg">
<h1 class="text-5xl font-bold text-white mb-3">β‘ TITAN HTTP Server</h1>
<p class="text-xl text-gray-300 mb-6">A Simplified Web Server Built Using Raw Linux System Calls</p>
<div class="max-w-3xl mx-auto text-left bg-gray-900 border border-gray-700 rounded-lg p-6 mb-6">
<p class="text-gray-300 mb-3">
<strong class="text-white">Description:</strong> This is a fully functional HTTP/1.1 server
that handles <strong class="text-white">thousands of concurrent connections</strong> using the same Linux kernel APIs (epoll, fork, pipe, sendfile), and systems programming fundamentals as nginx, Node.js, and Redis.
</p>
</div>
<div class="mt-6 flex flex-wrap justify-center gap-2">
<span class="inline-block bg-gray-700 text-gray-200 px-3 py-2 rounded text-sm font-medium">π§ Raw Linux Syscalls</span>
<span class="inline-block bg-gray-700 text-gray-200 px-3 py-2 rounded text-sm font-medium">β‘ epoll Event Loop</span>
<span class="inline-block bg-gray-700 text-gray-200 px-3 py-2 rounded text-sm font-medium">π§΅ Thread Pool</span>
<span class="inline-block bg-gray-700 text-gray-200 px-3 py-2 rounded text-sm font-medium">π Zero-Copy I/O</span>
<span class="inline-block bg-gray-700 text-gray-200 px-3 py-2 rounded text-sm font-medium">π CGI Support</span>
</div>
</div>
<!-- Real-Time Stats -->
<div class="bg-gray-800 border border-gray-700 rounded-lg p-8 mb-5">
<h2 class="text-2xl font-semibold text-white mb-4">π Live Server Statistics</h2>
<div class="bg-gray-900 border-l-4 border-gray-600 p-4 my-4 rounded">
<strong class="text-gray-200">What's happening:</strong> These metrics update by polling the <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">/stats</code> JSON endpoint.
The server tracks active connections using <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">epoll</code> and handles requests via a 4-thread pool.
<br><br>
<strong class="text-gray-200">π₯ Live Stress Testing:</strong> <span class="text-gray-300">Click "Start Test" to trigger real load testing! The server uses <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">curl + xargs -P 100</code> to send 100 parallel requests, bypassing browser limitations. As this was deployed on Railway, stress tests are capped at 500 requests to respect platform rate limits ... </span>
</div>
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-5 mt-5">
<div class="bg-gray-900 border border-gray-700 p-5 rounded-lg text-center">
<span class="block text-4xl font-semibold text-gray-100" id="total-requests">0</span>
<span class="block text-sm text-gray-400 mt-1">Total HTTP Requests</span>
<p class="text-xs text-gray-500 mt-2">Server-side counter (updates every 2s from /stats endpoint)</p>
</div>
<div class="bg-gray-900 border border-gray-700 p-5 rounded-lg text-center">
<span class="block text-4xl font-semibold text-gray-100" id="active-connections">0</span>
<span class="block text-sm text-gray-400 mt-1">Active Connections</span>
<p class="text-xs text-gray-500 mt-2">Live TCP sockets currently tracked by epoll (includes keep-alive)</p>
</div>
<div class="bg-gray-900 border border-gray-700 p-5 rounded-lg text-center">
<span class="block text-4xl font-semibold text-gray-100">4</span>
<span class="block text-sm text-gray-400 mt-1">Worker Threads</span>
<p class="text-xs text-gray-500 mt-2">Pre-allocated threads in the pool handling blocking I/O operations</p>
</div>
<div class="bg-gray-900 border border-gray-700 p-5 rounded-lg text-center">
<span class="block text-4xl font-semibold text-gray-100" id="stress-test-count">0</span>
<span class="block text-sm text-gray-400 mt-1">Live Stress Test</span>
<p class="text-xs text-gray-500 mt-2 mb-3">Status: <span id="stress-progress">0</span> / <span id="stress-target">0</span></p>
<select id="stress-request-count" class="w-full bg-gray-800 text-gray-200 border border-gray-600 rounded px-2 py-1 text-xs mb-2 font-mono">
<option value="10">10 requests</option>
<option value="100">100 requests</option>
<option value="500" selected>500 requests</option>
<option value="1000">1K requests</option>
<option value="5000">5K requests</option>
<option value="10000">10K requests</option>
</select>
<div class="flex gap-2 justify-center">
<button onclick="startStressTest()" id="stress-start-btn" class="bg-orange-700 text-white px-3 py-1.5 rounded text-xs font-medium hover:bg-orange-800 transition-colors">Start Test</button>
<button onclick="stopStressTest()" id="stress-stop-btn" class="bg-gray-700 text-gray-300 px-3 py-1.5 rounded text-xs font-medium hover:bg-gray-600 transition-colors" disabled>Stop Test</button>
</div>
</div>
</div>
</div>
<!-- Feature Demo 1: File Upload -->
<div class="bg-gray-800 border border-gray-700 rounded-lg p-8 mb-5">
<h2 class="text-2xl font-semibold text-white mb-4 flex items-center gap-2">π€ Feature #1: HTTP POST & File Upload</h2>
<div class="bg-gray-900 border-l-4 border-gray-600 p-4 my-4 rounded">
<strong class="text-gray-200">Systems Concept:</strong> Demonstrates HTTP request parsing, POST body extraction, and file I/O using <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">ofstream</code>.
Data is written to disk and persisted in <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">uploaded_data.txt</code>.
</div>
<textarea id="upload-content" rows="4" class="w-full p-3 bg-gray-900 border-2 border-gray-700 text-gray-200 rounded-md font-mono text-sm resize-y focus:outline-none focus:border-gray-600" placeholder="Type anything here... (Try JSON, code snippets, or text)">{"message": "Testing HTTP POST from browser", "timestamp": "2026-02-08"}</textarea>
<button onclick="uploadFile()" class="mt-4 bg-green-700 text-white px-6 py-2.5 rounded-md text-sm font-medium cursor-pointer transition-colors hover:bg-green-800">π€ Upload to Server</button>
<div id="upload-response" class="bg-gray-900 border-2 border-gray-700 rounded-md p-4 mt-4 font-mono text-gray-300 whitespace-pre-wrap max-h-48 overflow-y-auto hidden"></div>
</div>
<!-- Feature Demo 2: CGI Execution -->
<div class="bg-gray-800 border border-gray-700 rounded-lg p-8 mb-5">
<h2 class="text-2xl font-semibold text-white mb-4 flex items-center gap-2">π Feature #2: CGI (Common Gateway Interface)</h2>
<div class="bg-gray-900 border-l-4 border-gray-600 p-4 my-4 rounded">
<strong class="text-gray-200">Systems Concept:</strong> This triggers <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">fork()</code>, <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">execve()</code>, and <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">pipe()</code> syscalls to execute
<code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">time_server.py</code> as a child process. The output is captured via inter-process communication and returned as HTML.
<br><strong class="text-gray-200">Warning:</strong> This demo intentionally includes a 10-second <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">sleep()</code> to show the thread pool handling blocking I/O without freezing the server.
</div>
<button onclick="executeCGI()" class="bg-green-700 text-white px-6 py-2.5 rounded-md text-sm font-medium cursor-pointer transition-colors hover:bg-green-800">π Run Python Script (10s blocking demo)</button>
<div id="cgi-response" class="bg-gray-900 border-2 border-gray-700 rounded-md p-4 mt-4 font-mono text-gray-300 whitespace-pre-wrap max-h-48 overflow-y-auto hidden"></div>
</div>
<!-- Feature Demo 3: File Deletion -->
<div class="bg-gray-800 border border-gray-700 rounded-lg p-8 mb-5">
<h2 class="text-2xl font-semibold text-white mb-4 flex items-center gap-2">ποΈ Feature #3: HTTP DELETE Method</h2>
<div class="bg-gray-900 border-l-4 border-gray-600 p-4 my-4 rounded">
<strong class="text-gray-200">Systems Concept:</strong> Implements the HTTP DELETE verb and uses <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">remove()</code> syscall to delete files from the filesystem.
This demonstrates RESTful API implementation at a low level.
</div>
<input type="text" id="delete-path" value="/uploaded_data.txt" placeholder="/filename.txt" class="w-full p-3 bg-gray-900 border-2 border-gray-700 text-gray-200 rounded-md font-mono text-sm focus:outline-none focus:border-gray-600">
<button onclick="deleteFile()" class="mt-4 bg-red-700 text-white px-6 py-2.5 rounded-md text-sm font-medium cursor-pointer transition-colors hover:bg-red-800">ποΈ DELETE File</button>
<div id="delete-response" class="bg-gray-900 border-2 border-gray-700 rounded-md p-4 mt-4 font-mono text-gray-300 whitespace-pre-wrap max-h-48 overflow-y-auto hidden"></div>
</div>
<!-- Feature Demo 4: Session Management -->
<div class="bg-gray-800 border border-gray-700 rounded-lg p-8 mb-5">
<h2 class="text-2xl font-semibold text-white mb-4 flex items-center gap-2">πͺ Feature #4: HTTP Cookies & Session Management</h2>
<div class="bg-gray-900 border-l-4 border-gray-600 p-4 my-4 rounded">
<strong class="text-gray-200">Systems Concept:</strong> The server manually parses and sets HTTP <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">Set-Cookie</code> headers for stateful session tracking.
This demonstrates understanding of HTTP's stateless nature and client-side storage.
</div>
<button onclick="checkCookies()" class="bg-green-700 text-white px-6 py-2.5 rounded-md text-sm font-medium cursor-pointer transition-colors hover:bg-green-800">πͺ Check My Session</button>
<div id="cookie-display" class="bg-yellow-900 border border-yellow-700 text-yellow-100 p-2.5 rounded font-mono text-sm mt-4 hidden"></div>
</div>
<!-- Technical Architecture -->
<div class="bg-gray-800 border border-gray-700 rounded-lg p-8 mb-5">
<h2 class="text-2xl font-semibold text-white mb-4">ποΈ How This Compares to Production Servers</h2>
<div class="bg-gray-900 border-l-4 border-gray-600 p-4 my-4 rounded mb-5">
<strong class="text-gray-200">Context:</strong> <span class="text-gray-300">This is a <strong class="text-white">HTTP/1.1 web server</strong> β the same category as <strong class="text-white">nginx</strong>, <strong class="text-white">Apache</strong>, and the HTTP layer inside <strong class="text-white">Node.js</strong>.
It accepts TCP connections, parses HTTP requests, serves files, and executes backend scripts.</span>
<br><br>
<strong class="text-gray-200">What makes this different:</strong> <span class="text-gray-300">Most developers use high-level libraries (Express.js, Flask, Spring Boot) that <em>hide</em> how HTTP actually works.
This implementation exposes the raw Linux kernel APIs that <em>all</em> servers ultimately rely on.</span>
</div>
<h3 class="text-xl font-semibold text-white mt-6 mb-4">π Technical Implementation Breakdown</h3>
<div class="bg-gray-900 border border-gray-700 p-5 rounded-md border-l-4 border-l-gray-600 mb-4">
<h3 class="text-white mb-2.5 text-lg font-semibold">π§ epoll Event Loop (Like Node.js's libuv, Redis's Event Loop)</h3>
<p class="mb-2.5 text-gray-300">
<strong class="text-gray-200">What it does:</strong> Monitors thousands of network sockets simultaneously without blocking the CPU.
</p>
<p class="mb-2.5 text-gray-300">
<strong class="text-gray-200">How it works:</strong> Uses Linux's <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">epoll_wait()</code> syscall in <strong>edge-triggered mode</strong>.
When data arrives on any socket, the kernel wakes up the process instantly. O(1) complexity β unlike <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">select()</code> which is O(n).
</p>
<p class="text-gray-400 text-sm">
<strong class="text-gray-300">Real-world equivalent:</strong> nginx uses epoll. Node.js uses libuv (which wraps epoll on Linux). Redis uses epoll for pub/sub.
</p>
</div>
<div class="bg-gray-900 border border-gray-700 p-5 rounded-md border-l-4 border-l-gray-600 mb-4">
<h3 class="text-white mb-2.5 text-lg font-semibold">π§΅ Thread Pool Pattern (Like Apache Worker MPM, NGINX + FastCGI)</h3>
<p class="mb-2.5 text-gray-300">
<strong class="text-gray-200">What it does:</strong> Pre-allocates 4 worker threads to handle slow operations (disk I/O, script execution) without freezing the main event loop.
</p>
<p class="mb-2.5 text-gray-300">
<strong class="text-gray-200">How it works:</strong> Producer-Consumer pattern using <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">std::mutex</code> and <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">std::condition_variable</code>.
Tasks are queued, and idle threads pick them up. Avoids the overhead of <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">fork()</code>-ing a new process per request (like old CGI).
</p>
<p class="text-gray-400 text-sm">
<strong class="text-gray-300">Real-world equivalent:</strong> Apache's Worker MPM uses threads. Node.js offloads file I/O to a thread pool. Databases like PostgreSQL use background workers.
</p>
</div>
<div class="bg-gray-900 border border-gray-700 p-5 rounded-md border-l-4 border-l-gray-600 mb-4">
<h3 class="text-white mb-2.5 text-lg font-semibold">β‘ Zero-Copy Transfer with sendfile() (Like nginx, Kafka)</h3>
<p class="mb-2.5 text-gray-300">
<strong class="text-gray-200">What it does:</strong> Streams files from disk to network socket without copying data into user-space memory.
</p>
<p class="mb-2.5 text-gray-300">
<strong class="text-gray-200">How it works:</strong> Traditional I/O: <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">read(file) β copy to buffer β write(socket)</code> (4 context switches, 2 copies).
<code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">sendfile()</code>: Kernel transfers data directly from page cache to TCP buffer (2 context switches, 0 copies).
</p>
<p class="text-gray-400 text-sm">
<strong class="text-gray-300">Real-world equivalent:</strong> nginx uses sendfile for static files. Kafka uses it for log replication. CDN edge servers rely on this for performance.
</p>
</div>
<div class="bg-gray-900 border border-gray-700 p-5 rounded-md border-l-4 border-l-gray-600 mb-4">
<h3 class="text-white mb-2.5 text-lg font-semibold">π CGI Process Management (Like PHP-FPM, Early Web Servers)</h3>
<p class="mb-2.5 text-gray-300">
<strong class="text-gray-200">What it does:</strong> Executes Python scripts as separate processes and captures their output.
</p>
<p class="mb-2.5 text-gray-300">
<strong class="text-gray-200">How it works:</strong> Uses <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">fork()</code> to clone the server process, <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">pipe()</code> to create an IPC channel,
<code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">dup2()</code> to redirect stdout into the pipe, and <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">execve()</code> to replace the child process with Python. Parent reads the pipe.
</p>
<p class="text-gray-400 text-sm">
<strong class="text-gray-300">Real-world equivalent:</strong> Original Apache + CGI worked this way. PHP-FPM improved it with persistent processes. Modern frameworks (Express, Flask) use in-process handlers instead.
</p>
</div>
<h3 class="text-xl font-semibold text-white mt-8 mb-4">β What's Simplified (For Educational Purposes)</h3>
<div class="bg-gray-900 border-l-4 border-gray-600 p-4 my-4 rounded">
<p class="mb-2 text-gray-300">β <strong class="text-gray-200">No HTTPS/TLS:</strong> Production servers use OpenSSL/mbedTLS for encryption. Adding TLS requires implementing the TLS handshake.</p>
<p class="mb-2 text-gray-300">β <strong class="text-gray-200">No HTTP/2 or HTTP/3:</strong> This implements HTTP/1.1 only. HTTP/2 uses binary framing and multiplexing; HTTP/3 uses QUIC over UDP.</p>
<p class="mb-2 text-gray-300">β <strong class="text-gray-200">No Virtual Hosts:</strong> Can't host multiple domains on one IP (nginx can). Would need Host header routing.</p>
<p class="mb-2 text-gray-300">β <strong class="text-gray-200">No Load Balancing/Reverse Proxy:</strong> No upstream server pooling like nginx's proxy_pass.</p>
<p class="mb-2 text-gray-300">β <strong class="text-gray-200">No Compression:</strong> No gzip/brotli encoding (nginx has this built-in).</p>
<p class="mb-2 text-gray-300">β <strong class="text-gray-200">No Access Logs/Analytics:</strong> Production servers write to access.log, error.log with rotation.</p>
<p class="text-gray-300">β <strong class="text-gray-200">What we DO have:</strong> The core event loop, concurrency model, and I/O optimization that all servers need.</p>
</div>
<h3 class="text-xl font-semibold text-white mt-8 mb-4">π‘ More remarks on Generic HTTP Servers</h3>
<div class="bg-gray-900 border-l-4 border-gray-600 p-4 my-4 rounded">
<p class="mb-2.5 text-gray-300">
An <strong class="text-gray-200">HTTP server</strong> is just software that speaks the HTTP protocol β it's not tied to any specific use case.
nginx is an HTTP server (used for static files, reverse proxy). Apache is an HTTP server (used for hosting websites).
Node.js <em>contains</em> an HTTP server (the <code class="bg-gray-800 text-gray-300 px-1.5 py-0.5 rounded text-sm border border-gray-600 font-mono">http</code> module). Even REST APIs are HTTP servers.
</p>
</div>
</div>
</div>
<script src="/app.js"></script>
</body>
</html>