diff mrjunejune/src/blog/my-seobeo-journey/index.md @ 109:1c446ab6f945

[MrJuneJune] New Blog about writing Seobeo library.
author June Park <parkjune1995@gmail.com>
date Sat, 03 Jan 2026 19:37:51 -0800
parents
children 295ac2e5ec00
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mrjunejune/src/blog/my-seobeo-journey/index.md	Sat Jan 03 19:37:51 2026 -0800
@@ -0,0 +1,127 @@
+# Creating Network Library in C
+
+I’m so tired of modern web development. You want to spin up a simple web server, and suddenly you’re wrestling with a mountain of dependencies. Express, Fastify, whatever the flavor of the week is. They all promise simplicity, but dump a black hole of `node_modules` onto your machine. Have you ever actually looked inside? It’s insane. And all of them use React, Svelte, or whatever the current trend is for modern development. One time, I created a single React file using Bun and it had over 18k lines of JavaScript code lmao. And for what? To handle a simple HTTP request for a text file?
+
+<img src="/public/23k.png" />
+
+** It was actually 23K lines long lol.. you can test it [here](https://zenbu.babocoder.com/file/tip/playground). Just clone the repo and run `bazel build playground:hello` **
+
+
+## So, I decided to build my own network library from scratch, in C.
+
+I call it `seobeo` because that is how Korean people say "server" with an accent. The goal is simple: create something fast, lightweight, and completely transparent. No magic, no hidden layers. Just a pure, unadulterated networking layer, with a web server interface built on top of it.
+
+## Where to begin?
+
+I’d never really dealt with network libraries, nor had I written much C outside of a few contract jobs, so starting was a learning curve. I did a quick Google search and found an [amazing guide to network programming](https://beej.us/guide/bgnet/html/split/). In it, Beej talks about networking from scratch and explains many socket library functions in detail. He provides examples and explains the "why" behind the setup, so I highly recommend people check that out first.
+
+After that, I looked at a few examples from [Eskil Steenberg’s](https://www.google.com/search?q=https://www.quelsolaar.com/about/index.html) [GitHub repo](https://github.com/valiet/quel_solaar/tree/main/Testify), which was super useful for seeing how he approached API design.
+
+## The Core Concept
+
+The whole library is built around a central `Seobeo_Handle` struct. This struct handles all server-related information, holding everything from the socket file descriptor to the read/write buffers, as well as SSL-related data. This allows API callers to decide how they want to serialize the bytes and write/read from them.
+
+```c
+typedef struct {
+  int32           socket; 
+  Seobeo_SocketType  type;
+  boolean         connected; 
+
+  char            *host;
+  char            *port;
+
+  uint8           *read_buffer;
+  uint32          read_buffer_capacity;
+  uint32          read_buffer_len;
+  uint32          read_buffer_used; 
+
+  SSL_CTX_TYPE     *ssl_ctx;
+  SSL_TYPE         *ssl;
+
+  uint8           *write_buffer;
+  uint32          write_buffer_capacity;
+  uint32          write_buffer_len;
+
+  void            *file;
+  void            *text_copy;
+  char            *file_name;
+
+  atomic_bool destroyed;
+} Seobeo_Handle;
+
+```
+
+## Creating the Web Server Library
+
+From here, it was incredibly simple to create the web client and server logic, since all I had to do was send a string of bytes to request information. It was refreshing to be able to set exact header values without going through a library; receiving information byte-by-byte was actually fun.
+
+```c
+// Manually craft the raw HTTP request string
+char request[4096];
+int request_len = sprintf(
+  request,
+  "GET / HTTP/1.1\r\n"
+  "Host: example.com\r\n"
+  "Connection: close\r\n"
+  "\r\n"
+);
+
+// Queue the raw text...
+Seobeo_Handle_Queue(h, (uint8*)request, (uint32)request_len);
+// ...and flush it to the socket.
+int flush_result = Seobeo_Handle_Flush(h);
+
+```
+
+**While the logic is simple, I made plenty of mistakes along the way. I eventually had to create my own utility library (using Arenas, dynamic arrays, and hashmaps) just to make implementing the basic logic easier to manage.**
+
+Things only got complicated when I had to deal with SSL, as I wanted to be able to make encrypted calls, but I just had to hunker down and learn how SSL worked.
+
+On the server side, I kept the API dead simple: the server is granted access to a folder, and you can add your own router logic before initializing the server. As you can see below, your custom routing is always checked first, followed by static paths. I had to write a lot of code to handle different data types, but the logic remained straightforward. If you want to add a custom header, you just add it to the response hashmap.
+
+```c
+#include "seobeo/seobeo.h"
+
+// Handler for GET /api/v1/hello
+Seobeo_Request_Entry* GetHello(Seobeo_Request_Entry *req, Dowa_Arena *arena) {
+  Seobeo_Request_Entry *resp = NULL;
+  const char *body = "{\"message\": \"Hello from Seobeo!\"}";
+
+  // Build the response map
+  Dowa_HashMap_Push_Arena(resp, "status", "200", arena);
+  Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
+  Dowa_HashMap_Push_Arena(resp, "body", body, arena);
+  
+  return resp;
+}
+
+int main() {
+  Seobeo_Router_Init();
+  // Register the route
+  Seobeo_Router_Register("GET", "/api/v1/hello", GetHello);
+  // Start the server
+  Seobeo_Web_Server_Start("./public", "8080", SEOBEO_MODE_EDGE, 4);
+  return 0;
+}
+
+```
+
+No dependency injection, no middleware chains, no magic. Just a function that takes a request and returns a response. I updated the API so it can run as a multi-threaded, asynchronous process using system-level libraries like `epoll` or `kqueue`. I tested it with `Locust` at over 2,000 requests per second (my internet’s limit, lol) without Cloudflare, and it worked perfectly.
+
+## The Payoff and Trade-offs
+
+But here’s the best part: the final executable for my entire website, running on `seobeo`, is just **81 kB** (excluding static assets) and uses only **1.1 MB** of memory before server-side caching.
+
+That’s smaller than the `package.json` file of most modern web projects. It’s a rounding error in the world of Express or Python web frameworks. I understand that it doesn't have every feature, and people might worry about security (though I’m not too concerned since the server runs as a limited user with just static files), but it’s still a massive victory in my book.
+
+I know what you’re thinking. "But you have to write so much code" or "This code sucks" or whatever. And you're probably right. I have to manually craft HTTP headers. I have to manage my own memory with arena allocators. I even wrote my own integration test framework just to verify the HTTP client.
+
+But I’ll take that trade-off any day of the week.
+
+Why? Because I actually know what’s going on. The whole stack is right there in front of me. Plus, in the age of cloud infrastructure, most of the complex stuff is handled upstream anyway. My typical setup is **Cloudflare -> Nginx -> my server**. Cloudflare handles HTTPS; Nginx handles proxying and load balancing. Why should my application server bother with SSL handshakes when it’s sitting deep inside a trusted network? It’s redundant and just adds another layer of complexity.
+
+FYI, I am running this website on seobeo library and everything you see in this website from start to finish is written by me from now on.
+
+## TODOs?
+
+I’m planning to build out a WebSocket layer and an MCP (Message Control Protocol) implementation for some other crazy projects I have in mind, just to see how complicated they are to write because I like writing code. [Link to Library](https://zenbu.babocoder.com/file/tip/seobeo);