<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Sifundo - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Sifundo - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Thu, 11 Jun 2026 23:14:26 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/Sifundo/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Understand How Express.js Works by Building Your Own Server Multiplexer from Scratch ]]>
                </title>
                <description>
                    <![CDATA[ Kata Machines have become the go-to method for mastering tough concepts, and it's hard to find a better tool for deliberate practice. If you haven’t come across a kata yet, trust me—you will soon enough. There’s a reason why developers love katas, wh... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/understand-how-expressjs-works-by-building-your-own-server-multiplexer-from-scratch/</link>
                <guid isPermaLink="false">66feb8e20772faf5564db923</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ backend ]]>
                    </category>
                
                    <category>
                        <![CDATA[ webdev ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Express ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Sifundo ]]>
                </dc:creator>
                <pubDate>Thu, 03 Oct 2024 15:31:46 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/urBiLDuUhMU/upload/65f541a7f0d11691008b4e93d89f2d29.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Kata Machines have become the go-to method for mastering tough concepts, and it's hard to find a better tool for deliberate practice.</p>
<p>If you haven’t come across a kata yet, trust me—you will soon enough.</p>
<p>There’s a reason why developers love katas, whether they use them to sharpen their skills for personal projects or prepare for interviews.</p>
<p>A kata is all about <strong>deliberate</strong> practice. It comes from martial arts like Karate and Judo, and, according to Wikipedia, it’s defined as a pre-determined sequence of movements, techniques, and patterns that follow a specific order (source: <a target="_blank" href="https://en.wikipedia.org/wiki/Kata">wikipedia</a>).</p>
<p>Kata Machines come from this idea: learning through drills and deliberate, conscious (choreographed) practice.</p>
<p>I realized just how perfect katas are when I was learning Haskell back in the day. If you know, you know. Haskell was a beast to learn for me back then!</p>
<p>So, I thought, why not do the same for the backend? Just pick one high-level concept, and drill down on it repeatedly and deliberately to its core and first principles.</p>
<p>In this article, I picked server-side frameworks. We're going to pick apart the idea of a "framework" using Express as an example.</p>
<p>We’re going to take high-level Express:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);

<span class="hljs-keyword">const</span> PORT = <span class="hljs-number">3000</span>;
<span class="hljs-keyword">const</span> app = express();

app.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  res.send(<span class="hljs-string">"Hello, world!"</span>);
});

app.listen(PORT, <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Server listening on port:"</span>, PORT));
</code></pre>
<p>And drill all the way down, repeatedly, until we touch Node.js native code:</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">TCPWrap::New</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&lt;Value&gt;&amp; args)</span> </span>{
  CHECK(args.IsConstructCall());
  CHECK(args[<span class="hljs-number">0</span>]-&gt;IsInt32());
  Environment* env = Environment::GetCurrent(args);
  <span class="hljs-keyword">int</span> type_value = args[<span class="hljs-number">0</span>].As&lt;Int32&gt;()-&gt;Value();
  TCPWrap::SocketType type = <span class="hljs-keyword">static_cast</span>&lt;TCPWrap::SocketType&gt;(type_value);
  ProviderType provider;
  <span class="hljs-keyword">switch</span> (type) {
    <span class="hljs-keyword">case</span> SOCKET:
      provider = PROVIDER_TCPWRAP;
      <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> SERVER:
      provider = PROVIDER_TCPSERVERWRAP;
      <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">default</span>:
      UNREACHABLE();
  }
  <span class="hljs-keyword">new</span> TCPWrap(env, args.This(), provider);
}
</code></pre>
<p>And having gained this new intuition, we’ll build back up with a custom "Express" implementation:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">serverMux</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hook</span>(<span class="hljs-params">req, res</span>) </span>{
    <span class="hljs-comment">// To be implemented</span>
  }
  <span class="hljs-keyword">return</span> {
    hook
  };
}

<span class="hljs-keyword">const</span> app = serverMux();

<span class="hljs-keyword">const</span> server = http.createServer(<span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  app.hook(req, res);
});
</code></pre>
<p>It’s going to be quite the journey – and a rewarding one at that!</p>
<p>I'm assuming you have some backend knowledge and classify yourself as an advanced beginner who’s looking to level up.</p>
<p>If that sounds like you, we’re ready to proceed.</p>
<h3 id="heading-heres-what-well-cover">Here’s what we’ll cover:</h3>
<ul>
<li><p><a class="post-section-overview" href="#form-1--server-side-frameworks">Form 1: Server-Side Frameworks</a></p>
<ul>
<li><p><a class="post-section-overview" href="#first-drill--unpacking-expressjs">First Drill: Unpacking Express.js</a></p>
</li>
<li><p><a class="post-section-overview" href="#the-server">The Server</a></p>
</li>
<li><p><a class="post-section-overview" href="#the-socket-in-nodejs">The Socket in Node.js</a></p>
</li>
<li><p><a class="post-section-overview" href="#the-socket-in-nodejs-source-code">The Socket in Node.js Source Code</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#form-2--implementing-a-custom-server-mux">Form 2: Implementing a Custom Server Mux</a></p>
<ul>
<li><p><a class="post-section-overview" href="#creating-our-custom-router">Creating Our Custom Router</a></p>
</li>
<li><p><a class="post-section-overview" href="#basic-mux-skeleton">Basic Mux Skeleton</a></p>
</li>
<li><p><a class="post-section-overview" href="#the-hook-function">The Hook Function</a></p>
</li>
<li><p><a class="post-section-overview" href="#why-use-a-queue-">Why Use a Queue?</a></p>
<ul>
<li><a class="post-section-overview" href="#queue-operations">Queue Operations</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#request-wrapper">Request Wrapper</a></p>
</li>
<li><p><a class="post-section-overview" href="#testing-the-queue">Testing the Queue</a></p>
</li>
<li><p><a class="post-section-overview" href="#processing-requests">Processing Requests</a></p>
</li>
<li><p><a class="post-section-overview" href="#lookup-table-and-handlers">Lookup Table and Handlers</a></p>
</li>
<li><p><a class="post-section-overview" href="#registering-handlers">Registering Handlers</a></p>
</li>
</ul>
</li>
</ul>
<ul>
<li><a class="post-section-overview" href="#wrapping-up">Wrapping Up</a></li>
</ul>
<h2 id="heading-form-1-server-side-frameworks">Form 1: Server-Side Frameworks</h2>
<p>The term "server-side framework" is broad. Think about it: <code>mysql2</code> could be considered a framework depending on how you classify frameworks and libraries. Even <code>sharp.js</code> for image editing could fit under the umbrella of server-side frameworks, right?</p>
<p>But the question is, what type of framework is Express.js?</p>
<p>Express is a multiplexer—specifically, a server multiplexer (server mux). I promise, the term isn’t as complex as it sounds. The implementation, though—that’s a whole different story.</p>
<p>In simple terms, a server mux is a router. Of course, Express and other server muxes handle more than just routing, but that’s the core idea.</p>
<p>Express takes in <code>request</code> and <code>response</code> objects from the server and routes them. Don’t worry, we’ll dive into routing soon.</p>
<p>Here’s an interesting point: if Express isn’t the server, then what exactly is the server?</p>
<p>To answer that, we need to look at the Express.js source code, which you can clone from GitHub:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/expressjs/express.git
</code></pre>
<p>Once you’re set, we can dive right in with our first deep dive.</p>
<h3 id="heading-first-drill-unpacking-expressjs">First Drill: Unpacking Express.js</h3>
<p>Open your Express source code in an editor. You’ll find the entry file <code>express.js</code> in the <code>lib</code> folder.</p>
<p>You can skim the file, but we’re going to focus on lines 42 and 43—the heart of it all:</p>
<pre><code class="lang-js">mixin(app, EventEmitter.prototype, <span class="hljs-literal">false</span>);
mixin(app, proto, <span class="hljs-literal">false</span>);
</code></pre>
<p>What you’re looking at is object composition: a design pattern where an object is created by combining the properties and methods of other objects.</p>
<p>Our target object here is <code>proto</code>, which is imported from <code>application.js</code>, the core of Express.</p>
<p>Let’s open that file. There’s a lot of code, but remember, our goal is to figure out where the server is within Express.</p>
<p>If there’s one function in Express that everyone likely knows, it’s <code>listen</code>. The essence of a server is to "listen" over a network. So, do a quick <code>Ctrl+F</code> for "listen," and you’ll find the definition on line 633:</p>
<pre><code class="lang-js">app.listen = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">listen</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">var</span> server = http.createServer(<span class="hljs-built_in">this</span>);
  <span class="hljs-keyword">return</span> server.listen.apply(server, <span class="hljs-built_in">arguments</span>);
};
</code></pre>
<p>There it is, the famous <code>listen</code> function. Did we just find the server?</p>
<pre><code class="lang-js"><span class="hljs-keyword">var</span> server = http.createServer(<span class="hljs-built_in">this</span>);
</code></pre>
<p>We’ve already seen a version of this in the intro:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> server = http.createServer(<span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  app.hook(req, res);
});
</code></pre>
<p>This confirms that Express is indeed a server mux, and the actual server is returned by the Node.js <code>createServer</code> function from the <code>http</code> package.</p>
<p>That’s some solid progress!</p>
<p>We’ve peeled back a layer, but we can go deeper. What exactly does <code>createServer</code> do, and what is this <code>server</code> object?</p>
<h3 id="heading-the-server">The Server</h3>
<p>A server is the basic unit of the backend. At its core, the concept is simple: how can two or more processes communicate over a network?</p>
<p>This is the fundamental idea behind network programming. We have devices equipped with IP addresses for identification and ports for data exchange over a network.</p>
<p>The communication itself is complex, which is where protocols come in to facilitate the process.</p>
<p>The most common protocols are UDP and TCP:</p>
<ul>
<li><p><strong>UDP</strong> is a connectionless protocol and does not guarantee reliable communication, but allows for low-latency and efficient data transfer. This is ideal for time-sensitive applications such as video conferencing, online gaming, and voice over IP (VoIP) (source <a target="_blank" href="https://en.wikipedia.org/wiki/User_Datagram_Protocol">Wikipedia</a>).</p>
</li>
<li><p><strong>TCP</strong> is a connection-oriented protocol with reliable, ordered, and error-checked data transmission between applications on networked devices. It’s a major part of internet applications (source <a target="_blank" href="https://en.wikipedia.org/wiki/Transmission_Control_Protocol">Wikipedia</a>).</p>
</li>
</ul>
<p>TCP is the most widely used protocol due to its reliability, and most server-side applications you’ll work with, including Express, are TCP-based.</p>
<p>Although I love the quirks and power of UDP, we’ll focus on TCP, tracing its roots in Node.js.</p>
<p>We’ve already seen a glimpse of this:</p>
<pre><code class="lang-c"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">TCPWrap::New</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&lt;Value&gt;&amp; args)</span> </span>{
  <span class="hljs-comment">// some code</span>
  <span class="hljs-keyword">new</span> TCPWrap(env, args.This(), provider);
}
</code></pre>
<p>Before we dig into that, we need to answer a key question: What does it really mean to be a server process?</p>
<p>Without getting too deep into file descriptors, sockets, or network layers, a server is an OS-level object responsible for handling communication between nodes. When you call:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> http = <span class="hljs-built_in">require</span>(<span class="hljs-string">"node:http"</span>);

<span class="hljs-keyword">const</span> something = http.createServer({});
</code></pre>
<p>You’re creating an OS-level object, commonly known as a <strong>socket</strong>. This socket facilitates network communication between devices, along with handling data encoding and decoding.</p>
<p>In short, <code>createServer</code> abstracts and returns this socket object.</p>
<p>And, yes, we can implement this socket in Node.js. Remember, Node.js has native access to the OS, allowing JavaScript to function at the system level.</p>
<h3 id="heading-the-socket-in-nodejs">The Socket in Node.js</h3>
<p>Here’s some code that creates a server socket:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Using Node v20</span>
<span class="hljs-keyword">const</span> net = <span class="hljs-built_in">require</span>(<span class="hljs-string">'node:net'</span>);

<span class="hljs-keyword">const</span> server = net.createServer(<span class="hljs-function">(<span class="hljs-params">c</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'client connected'</span>, c.remoteAddress);
  c.write(<span class="hljs-string">"Hello; world"</span>);

  c.on(<span class="hljs-string">'end'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'client disconnected'</span>);
  });
});

server.on(<span class="hljs-string">'error'</span>, <span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> {
  <span class="hljs-keyword">throw</span> err;
});

server.listen(<span class="hljs-number">3000</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'server bound'</span>);
});
</code></pre>
<p>While <code>net.createServer((c)</code> is still a high-level abstraction like <code>http.createServer</code>, it returns the raw socket.</p>
<p>The <code>c</code> object represents the client that made the connection (dial). Beyond writing to it, we can do much more.</p>
<p>For instance, here’s a simple write operation:</p>
<pre><code class="lang-js">c.write(<span class="hljs-string">"Hello world"</span>);
</code></pre>
<p>Our socket is running on <code>localhost:3000</code>. If you make a request (or use <code>curl</code>):</p>
<pre><code class="lang-bash">curl localhost:3000
</code></pre>
<p>The OS-level network stack encodes not only your data but also information about who you are and where to find you—in the form of a response, among other things.</p>
<p>This is what the server receives, and it’s important to know where to send the response (like IP, and so on).</p>
<p>So, the <code>c</code> object represents all of that!</p>
<p>We’ve covered a lot of the surface-level concepts, but before we wrap up this part, here’s a bonus challenge:</p>
<p>Try writing a class on the server to manage multiple connections. You could store these connections in a data structure and periodically send data to them while the connection remains open.</p>
<p>We’re about three layers deep now, but the journey isn’t over. Remember the goal?</p>
<p>Now it’s time to clone the Node.js source code. Don’t worry, we’ll only focus on the relevant parts.</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/nodejs/node.git
</code></pre>
<h3 id="heading-the-socket-in-nodejs-source-code">The Socket in Node.js Source Code</h3>
<p>Let the tracing begin! Node.js is a massive codebase – it’s an entire engine that does way more than just handle sockets. But we only care about the networking part today.</p>
<p>First, navigate to the <code>lib</code> folder, and inside you’ll find a file called <code>net.js</code>. This is where most of the work happens for network applications. If you scroll down to line 210, you’ll see a familiar sight:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createServer</span>(<span class="hljs-params">options, connectionListener</span>) </span>{
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Server(options, connectionListener);
}
</code></pre>
<p>That’s it! Every time we create a server, it calls this function and returns a <code>Server</code> object. Anytime you see <code>new</code> in JavaScript, you should have a lightbulb moment—it means a new object or class (blueprint) is being created.</p>
<p>So we can trace and find the <code>Server</code> definition:</p>
<p>On line 1737</p>
<p>At first glance, it might seem like nothing special is happening. But JavaScript has a sneaky way of hiding complexity.</p>
<p>Here’s the thing: JavaScript is a prototype-based language. This means that objects can inherit features from other objects through prototypes. On line 1791, we see this in action:</p>
<pre><code class="lang-js">ObjectSetPrototypeOf(Server.prototype, EventEmitter.prototype);
</code></pre>
<p>In plain English: our <code>Server</code> object is inheriting all the behavior from other objects like <code>EventEmitter</code>, for example. This is a common pattern in JavaScript libraries – remember the mixin in Express?</p>
<p>At this point, if you’ve never worked with prototypes or Object-Oriented JavaScript (OOJS), this might feel like advanced territory. But don’t worry – the good folks at <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain">MDN</a> have an excellent guide on prototypes to get you up to speed.</p>
<p>Now, what’s one thing we know for sure about a Node.js server? It has a <code>listen</code> function. We use it all the time in server-side code (even in frameworks like Express). So, let’s check if our <code>Server</code> object has a <code>listen</code> function.</p>
<p>Scroll down a bit more, and there it is on line 2006:</p>
<pre><code class="lang-js">Server.prototype.listen = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">...args</span>) </span>{}
</code></pre>
<p>This function handles a lot of stuff—like validating the port number—but the key part starts around line 2016, where the comment clearly tells us:</p>
<pre><code class="lang-js"><span class="hljs-comment">// start TCP server listening on host:port</span>
</code></pre>
<p>We know what TCP is!</p>
<p>The important functions here are <code>lookupAndListen</code> and <code>listenInCluster</code>. They are responsible for starting the actual TCP server:</p>
<pre><code class="lang-js"><span class="hljs-comment">// start TCP server listening on host:port</span>
<span class="hljs-keyword">if</span> (options.host) {
  lookupAndListen(<span class="hljs-built_in">this</span>, options.port | <span class="hljs-number">0</span>, options.host, backlog, options.exclusive, flags);
} <span class="hljs-keyword">else</span> {
  listenInCluster(<span class="hljs-built_in">this</span>, <span class="hljs-literal">null</span>, options.port | <span class="hljs-number">0</span>, <span class="hljs-number">4</span>, backlog, <span class="hljs-literal">undefined</span>, options.exclusive);
}
</code></pre>
<p>Digging into <code>lookupAndListen</code> (line 2156), we find that it calls <code>listenInCluster</code>, which leads us to another function: <code>server._listen2</code> (yep, more tracing!):</p>
<pre><code class="lang-js">server._listen2(address, port, addressType, backlog, fd, flags);
</code></pre>
<p>As the comments explain, this is all about backward compatibility:</p>
<pre><code class="lang-js"><span class="hljs-comment">// _listen2 sets up the listened handle, it is still named like this</span>
<span class="hljs-comment">// to avoid breaking code that wraps this method</span>
</code></pre>
<p>I know this might feel like a wild goose chase, but trust me, tracing through a large codebase like Node.js requires patience. We’re getting close.</p>
<p>So, <code>._listen2</code> is defined in our <code>Server</code> object’s prototype and points to a function called <code>setupListenHandle</code> (line 1856). This function is the real hub where everything comes together.</p>
<p>Around line 1870 and 1883, you’ll find the function <code>createServerHandle</code>:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createServerHandle</span>(<span class="hljs-params">address, port, addressType, fd, flags</span>) </span>{
   handle = <span class="hljs-keyword">new</span> TCP(TCPConstants.SERVER);
   isTCP = <span class="hljs-literal">true</span>;
   <span class="hljs-keyword">return</span> handle;
}
</code></pre>
<p>Finally! We’ve hit the core: the <code>TCP</code> object. This is where the actual TCP server is created, the core. We could stop here, satisfied that we’ve found the TCP server, but why not dig deeper?</p>
<p>Remember that <code>new TCP</code> is creating an object, so we need to figure out what <code>TCP</code> actually represents.</p>
<p>Go back up to line 68, where you’ll see the following import:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> {
  TCP,
  TCPConnectWrap,
  <span class="hljs-attr">constants</span>: TCPConstants,
} = internalBinding(<span class="hljs-string">'tcp_wrap'</span>);
</code></pre>
<p>This is where things get interesting. You might wonder: “What kind of import is that? It’s not your regular <code>require</code> or <code>import</code> statement.” That’s because JavaScript alone can’t handle TCP servers—it needs help from C++.</p>
<p>Node.js, which is built on the V8 engine, relies on C++ bindings to do the heavy lifting. These bindings are like a bridge, allowing JavaScript to communicate with low-level system functions (like creating a TCP server). <code>internalBinding('tcp_wrap')</code> is one of these bridges.</p>
<p>To truly trace things to their source, we need to dive into the Node.js C++ code. You’ll find <code>tcp_wrap.cc</code> in the <code>src</code> folder (among others like <code>crypto</code>, <code>streams</code>, <code>async</code>, <code>fs</code>). Open it, and you’ll find this function:</p>
<pre><code class="lang-cpp"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">TCPWrap::New</span><span class="hljs-params">(<span class="hljs-keyword">const</span> FunctionCallbackInfo&lt;Value&gt;&amp; args)</span> </span>{
  CHECK(args.IsConstructCall());
  CHECK(args[<span class="hljs-number">0</span>]-&gt;IsInt32());
  Environment* env = Environment::GetCurrent(args);
  <span class="hljs-keyword">int</span> type_value = args[<span class="hljs-number">0</span>].As&lt;Int32&gt;()-&gt;Value();
  TCPWrap::SocketType type = <span class="hljs-keyword">static_cast</span>&lt;TCPWrap::SocketType&gt;(type_value);
  ProviderType provider;
  <span class="hljs-keyword">switch</span> (type) {
    <span class="hljs-keyword">case</span> SOCKET:
      provider = PROVIDER_TCPWRAP;
      <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> SERVER:
      provider = PROVIDER_TCPSERVERWRAP;
      <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">default</span>:
      UNREACHABLE();
  }
  <span class="hljs-keyword">new</span> TCPWrap(env, args.This(), provider);
}
</code></pre>
<p>This is where the TCP server is <em>actually</em> created. You can see more familiar functions like <code>bind</code>, and everything JavaScript does is just a mirror of these lower-level operations.</p>
<p>We’ve traced our way from high-level JavaScript all the way down to C++—the true beginning of a TCP server in Node.js.</p>
<p>We've completed the first part of the introduction: "And drill all the way down repeatedly until we touch Node.js native code" and now it's time to build up.</p>
<h2 id="heading-form-2-implementing-a-custom-server-mux">Form 2: Implementing a Custom Server Mux</h2>
<p>Before diving into the code, the goal isn’t to focus on the complexity of mux (multiplexer) development (because that can get complicated). Instead, it’s to show how the <strong>server</strong> and <strong>mux</strong> fit together.</p>
<p>If anything, this is the key takeaway: the flow from the server to the router, and ultimately to the caller (the client that made the request).</p>
<p>Remember, we've already seen a similar concept in Express:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Express app inherits from Node's EventEmitter</span>
mixin(app, EventEmitter.prototype, <span class="hljs-literal">false</span>);
<span class="hljs-comment">// Implements the server mux with functions like listen, handle, middleware</span>
mixin(app, proto, <span class="hljs-literal">false</span>);
</code></pre>
<p>Behind the scenes, a lot of complex code is abstracted away. This helps simplify things and makes the code cleaner, but for teaching purposes, we’ll take a more verbose approach. This way, you can see how everything connects.</p>
<h3 id="heading-creating-our-custom-router">Creating Our Custom Router</h3>
<p>Let's start simple and build a basic server. You probably already know how to create a native server in Node.js:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> server = http.createServer(<span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
   app.hook(req, res);
});
</code></pre>
<p>Here, we’re introducing an object <code>app</code> with a <code>hook</code> function (which we’ll implement shortly). This is where the server redirects the <code>req</code> and <code>res</code> to our custom router. This <strong>hook</strong> is the meeting point—the interaction between the server and the router (mux).</p>
<h3 id="heading-basic-mux-skeleton">Basic Mux Skeleton</h3>
<p>Let's start by creating the structure of our mux:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">serverMux</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hook</span>(<span class="hljs-params">req, res</span>) </span>{
    <span class="hljs-comment">// To be implemented</span>
  }
  <span class="hljs-keyword">return</span> {
    hook
  };
}

<span class="hljs-keyword">const</span> app = serverMux();

<span class="hljs-keyword">const</span> server = http.createServer(<span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  app.hook(req, res);
});
</code></pre>
<h3 id="heading-the-hook-function">The Hook Function</h3>
<p>The <code>hook</code> function is our middleman between the server and the mux. It receives the request (<code>req</code>) and response (<code>res</code>) objects from the server and passes them to our mux:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hook</span>(<span class="hljs-params">req, res</span>) </span>{
    requestsQueue.push(requestWrapper(req, res));
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"new request!"</span>);
    processRequests();
}
</code></pre>
<p>Here, we introduced a few new things:</p>
<ul>
<li><p><code>requestWrapper</code>: A function to wrap the <code>req</code> and <code>res</code>.</p>
</li>
<li><p><code>processRequests</code>: A function to handle the request processing.</p>
</li>
<li><p><code>requestsQueue</code>: A basic JavaScript array that will act as our queue for handling requests.</p>
</li>
</ul>
<p>Let's update <code>serverMux</code> to reflect this:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">serverMux</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> requestsQueue = [];

    <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">processRequests</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-comment">// To be implemented</span>
    }

    <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hook</span>(<span class="hljs-params">req, res</span>) </span>{
      requestsQueue.push(requestWrapper(req, res));
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"new request!"</span>);
      processRequests();
    }

    <span class="hljs-keyword">return</span> {
      hook
    };
}
</code></pre>
<h3 id="heading-why-use-a-queue">Why Use a Queue?</h3>
<p>You might be wondering why we’re using a queue instead of handling requests immediately like Express does with <code>app.handle</code>. Well, storing requests in a queue helps simulate an event loop. This will give us better visibility into how requests are processed, one at a time.</p>
<h4 id="heading-queue-operations">Queue Operations</h4>
<p>A queue is a first-in, first-out (FIFO) data structure. Just like a line at the store, the request that arrives first gets processed first.</p>
<p>In our case, the <code>requestsQueue</code> is an array. Here’s how we’ll handle enqueueing and dequeueing:</p>
<ul>
<li><p><strong>Enqueue (push)</strong>: We push requests into the queue with <code>requestsQueue.push(requestWrapper(req, res));</code></p>
</li>
<li><p><strong>Dequeue (shift)</strong>: We pull the next request out of the queue with <code>const c = requestsQueue.shift();</code></p>
</li>
</ul>
<h3 id="heading-request-wrapper">Request Wrapper</h3>
<p>The <code>requestWrapper</code> function is a simple utility that wraps the incoming <code>req</code> and <code>res</code> objects, and extracts some useful information:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">requestWrapper</span>(<span class="hljs-params">req, res</span>) </span>{
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">url</span>: req.url,
      <span class="hljs-attr">method</span>: req.method,
      req,
      res
    };
}
</code></pre>
<p>In more advanced frameworks like <a target="_blank" href="https://hono.dev/">Hono.js</a>, the request wrapper might add additional functionality, such as helper methods for setting headers or parsing body content. For now, we’re keeping things simple and just returning the request and response with the URL and method.</p>
<h3 id="heading-testing-the-queue">Testing the Queue</h3>
<p>Let’s test this out by logging the request queue on every new request. Update your <code>hook</code> function:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">hook</span>(<span class="hljs-params">req, res</span>) </span>{
    requestsQueue.push(requestWrapper(req, res));
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"New request queued!"</span>, requestsQueue);
    processRequests();
}
</code></pre>
<p>Start the server with:</p>
<pre><code class="lang-bash">node index.js
</code></pre>
<p>Now, open another terminal and make a request to the server:</p>
<pre><code class="lang-bash">curl http://localhost:3000
</code></pre>
<p>You should see the queue logged in the console. The terminal might look like it's hanging because we haven’t responded to the request yet. You can exit the process manually for now.</p>
<h3 id="heading-processing-requests">Processing Requests</h3>
<p>Here’s the full <code>processRequests</code> function:</p>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">processRequests</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">while</span> (requestsQueue.length &gt; <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">const</span> c = requestsQueue.shift();
        <span class="hljs-keyword">if</span> (c) {
            <span class="hljs-keyword">const</span> handler = lookupTable[c.url] || lookupTable[<span class="hljs-string">"/notfound"</span>];
            <span class="hljs-keyword">if</span> (handler) {
                (<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
                    handler(c.req, c.res);
                })();
            } <span class="hljs-keyword">else</span> {
                <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Missing not found handler!"</span>);
            }
        }
    }
}
</code></pre>
<p>Let’s break it down:</p>
<ol>
<li><p><strong>Queue processing</strong>: We loop through the queue, dequeueing each request one by one.</p>
</li>
<li><p><strong>Handler lookup</strong>: For each request, we check if a handler exists in the <code>lookupTable</code> for the URL. If it doesn’t, we fall back to a <code>/notfound</code> handler.</p>
</li>
<li><p><strong>Handler execution</strong>: We execute the handler, passing the request and response objects.</p>
</li>
</ol>
<h3 id="heading-lookup-table-and-handlers">Lookup Table and Handlers</h3>
<p>We need a way to map URLs to their respective handlers. This is where the <code>lookupTable</code> comes in:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> lookupTable = {
    <span class="hljs-string">"/"</span>: <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
      res.writeHead(<span class="hljs-number">200</span>, { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'text/plain'</span> });
      res.end(<span class="hljs-string">'Hello, World!\n'</span>);
    },
    <span class="hljs-string">"/notfound"</span>: <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
      res.writeHead(<span class="hljs-number">404</span>, { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'text/plain'</span> });
      res.end(<span class="hljs-string">'404 Not Found\n'</span>);
    }
};
</code></pre>
<p>When a request comes in, we check if the URL matches an entry in the table. If it does, we call the corresponding handler function.</p>
<p>For example, calling <code>curl http://localhost:3000</code> will hit the <code>/</code> route and return "Hello, World!". If you hit a non-existent route like <code>/random</code>, it will trigger the 404 handler.</p>
<h3 id="heading-registering-handlers">Registering Handlers</h3>
<p>Finally, let’s add a method to register new handlers dynamically:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">serverMux</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> lookupTable = {};

  <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">registerHandler</span>(<span class="hljs-params">path, handler</span>) </span>{
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> path !== <span class="hljs-string">'string'</span> || !path) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Path must be a non-empty string"</span>);
    }
    <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> handler !== <span class="hljs-string">'function'</span>) {
      <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Handler must be a function"</span>);
    }
    lookupTable[path] = handler;
  }

  <span class="hljs-keyword">return</span> {
    hook,
    registerHandler
  };
}
</code></pre>
<p>Now, we can dynamically register new routes with their handlers:</p>
<pre><code class="lang-js">app.registerHandler(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    res.writeHead(<span class="hljs-number">200</span>, { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'text/plain'</span> });
    res.end(<span class="hljs-string">'Home Page\n'</span>);
});

app.registerHandler(<span class="hljs-string">"/about"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    res.writeHead(<span class="hljs-number">200</span>, { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'text/plain'</span> });
    res.end(<span class="hljs-string">'About Us\n'</span>);
});
</code></pre>
<p>Here's a full example of <code>registerHandler</code> in action:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> app =  serverMux()


app.registerHandler(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>)=&gt;</span> {

  res.writeHead(<span class="hljs-number">200</span>, { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'text/plain'</span> });

  res.end(<span class="hljs-string">'Hello, World!'</span>);



})

app.registerHandler(<span class="hljs-string">"/about"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>)=&gt;</span> {

    res.writeHead(<span class="hljs-number">200</span>, { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'text/html'</span> });

    res.end(<span class="hljs-string">'&lt;h1&gt;About Us&lt;/h1&gt;'</span>);

})


app.registerHandler(<span class="hljs-string">"/contact"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>)=&gt;</span> {

  res.writeHead(<span class="hljs-number">200</span>, { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'text/html'</span> });

  res.end(<span class="hljs-string">'&lt;h1&gt;Contact Us&lt;/h1&gt;'</span>);

})


app.registerHandler(<span class="hljs-string">"/api/data"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>)=&gt;</span> {

  res.writeHead(<span class="hljs-number">200</span>, { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'application/json'</span> });

  res.end(<span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Some data from the API'</span> }));

})


app.registerHandler(<span class="hljs-string">"/notfound"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>)=&gt;</span> {

   res.writeHead(<span class="hljs-number">404</span>, { <span class="hljs-string">'Content-Type'</span>: <span class="hljs-string">'text/plain'</span> });

    res.end(<span class="hljs-string">'404 Not Found'</span>);

})



<span class="hljs-keyword">const</span> server = http.createServer(<span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {

   <span class="hljs-built_in">console</span>.log(req.url)

   app.hook(req, res)

});
</code></pre>
<p>Notice how similar it is to Express?</p>
<pre><code class="lang-js">app.get(<span class="hljs-string">"/"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>)=&gt;</span> {

})
</code></pre>
<p>Just a bit more verbose!</p>
<p>Now, run the server and put it to the test by pasting this into your terminal:</p>
<pre><code class="lang-bash"><span class="hljs-keyword">for</span> /l %i <span class="hljs-keyword">in</span> (1,1,100) <span class="hljs-keyword">do</span> curl -X GET http://localhost:3000
</code></pre>
<p>This will send 100 requests. Try opening two or more terminals and running the same command concurrently to see how your server handles the load.</p>
<p>Congratulations! You’ve built a basic server multiplexer (mux). It may not revolutionize the world, but it's a solid starting point to understand how routing works in web frameworks.</p>
<h1 id="heading-wrapping-up">Wrapping Up</h1>
<p>In this article, we took a deep dive into the concept of server-side frameworks, using Express as our primary example. We traced it from its high-level abstractions all the way down to the native TCP server built in C++. Then, to cement these ideas, we built our own simple server mux.</p>
<p>It’s a powerful learning exercise, because we stripped away the magic and dug into the core of how things work. While this example is just the tip of the iceberg, it gives you the tools to explore even deeper. For a challenge, look into how Express handles pattern matching and registering routes—try improving our simple mux!</p>
<p>I left out more advanced topics like updating our queue with a linked list and simulating concurrent requests, so this is something you can explore.</p>
<p>Thanks for reading! I hope you enjoyed this exploration as much as I did writing it. If you have any thoughts, questions, or just want to connect I am on <a target="_blank" href="https://x.com/codelit09">x</a>, feel free to reach out.</p>
<p>And of course, enjoy your timezone!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
