Getting a Web Server running on my hobby OS on OSHub

💥 Read this insightful post from Hacker News 📖

📂 Category:

✅ Here’s what you’ll learn:

After a long break from working on my hobby operating system, I finally got back into it and finished a very important milestone: a working web server.

Web browser accessing HTTP server on my OS

Networking was always integral to my hobby project. The first goal was getting the basic networking stack working: Ethernet, IP, ARP, UDP, TCP, DHCP and DNS. Besides TCP this was rather straightforward, but when moving onto HTTP things broke.

First time getting TCP to work.


Networking stack code

This led to my first break from the project, but also left a nagging thought in my mind, wanting to make it work. I finally sat down and started debugging. 

I eventually found the culprit after hours of dissecting my own code, the problem was a broken implementation of the terminal buffer, overwriting a lock in another process… fun. Additionally, the E1000 network driver did not correctly handle incoming packets, which I finally got working by handling bursts of packets.

After getting an HTML page returned from the web engine I started noticing lots of performance errors and hangs from TCP, mainly because quickly refreshing the browser led to a spam of RST packets which were not handled correctly.

After a few hours of tinkering I finally got the RST packets working and the network stack is now able to handle a packet spam from the browser.

Next step was actually implementing a HTTP engine, parsing the requests from the user. Before this engine I simply returned a static HTTP response no matter the actual request.

Keeping with the spirit of this hobby OS I want to write everything from scratch, luckily I already had implemented a pretty complete HTTP parser for my other project c-web-modules. So I extracted the HTTP parser as a standalone library and ported it to my OS.

After the HTTP engine was done I moved onto the web engine, focusing on something small, rather than big and fancy. Mainly routing was important and adding route handlers. Allowing the user to specify a route, method and lambda function handler.
/* Simple routing */
engine.get("https://oshub.org/", [](const http::Request& req, http::Response& res) ⚡);
It’s a tiny example, but it mirrors how a lot of modern C++ and web frameworks think about routing: match a path + method, call a handler, build a response.
#lang:plaintext
[ Browser ]
    |
    v
[ Web Server (userspace):
  WebEngine | HTTPEngine | FileRepository ]
    |
    v
[ Network stack:
  TCP/UDP | IP | ARP | DHCP | DNS | Ethernet(E1000) ]
The last step was updating the userspace program with the new HTTP and Web engine. Finally I added a way to serve files using a FileRepository which supports caching. Now I can edit the files inside the operating system and then serve them with the web server.
#lang:cpp
WebEngine webEngine(80, 16);
web::FileRepository fileRepo;

/* Simple static pages */
webEngine.get("/home", [&fileRepo](const http::Request& req, http::Response& res) Tell us your thoughts in comments!);

webEngine.get("/about", [&fileRepo](const http::Request& req, http::Response& res) ⚡);

webEngine.get("/status", [&fileRepo](const http::Request& req, http::Response& res) Share your opinion below!);

webEngine.run();

The next thing on the TODO list will be to add a more fancy UI for the webserver and a way to close it gracefully.

(Graceful shutdown is one of those “boring” features you don’t miss… until the first time you corrupt something on exit.)

When this is finished, the biggest task so far will begin… the web browser.

💬 What do you think?

#️⃣ #Web #Server #running #hobby #OSHub

🕒 Posted on 1764351419

By

Leave a Reply

Your email address will not be published. Required fields are marked *