<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Armaan Chahal</title>
    <description>The latest articles on Forem by Armaan Chahal (@armaancpro).</description>
    <link>https://forem.com/armaancpro</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3480661%2F64b32be9-40f7-45de-b015-1d7e85931925.jpg</url>
      <title>Forem: Armaan Chahal</title>
      <link>https://forem.com/armaancpro</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/armaancpro"/>
    <language>en</language>
    <item>
      <title>Coroutines &amp; Concurrent HTTP and a Templating Engine in C++ (Part 2)</title>
      <dc:creator>Armaan Chahal</dc:creator>
      <pubDate>Tue, 16 Dec 2025 04:18:49 +0000</pubDate>
      <link>https://forem.com/armaancpro/coroutines-concurrent-http-and-a-templating-engine-in-c-part-2-337n</link>
      <guid>https://forem.com/armaancpro/coroutines-concurrent-http-and-a-templating-engine-in-c-part-2-337n</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Today we'll cover asynchronous programming in action with Boost.Asio and coroutines.&lt;br&gt;
This will level up your server from lowly, blocking calls, to a snappy concurrent process.&lt;br&gt;
As a bonus, we'll cover templating at the end, which is a nice and easy way to wrap up the series.&lt;br&gt;
If you want to skip the lore dump, skip to the code.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting Started With Concurrency
&lt;/h2&gt;

&lt;p&gt;If you haven't yet, read &lt;a href="https://amn.sh/blog/2025-12-14-http-server-in-cpp" rel="noopener noreferrer"&gt;part 1&lt;/a&gt; for more info on the fundamentals of raw HTTP in C++.&lt;/p&gt;

&lt;p&gt;Yes, half of Boost.Asio is concurrency; the other half is I/O (networking in particular).&lt;br&gt;
Therefore, you may assume that Asio would make concurrency easy.&lt;br&gt;
And you'd be right! With the power of Asio and C++ Coroutines, writing concurrent networked code is &lt;strong&gt;relatively&lt;/strong&gt; easy!&lt;/p&gt;

&lt;p&gt;We'll end with the templating engine, as that is quite short and a fun way to wrap up this series.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Idea
&lt;/h2&gt;

&lt;p&gt;We're talking about coroutines here. Asio sorts of amplifies the power of coroutines but doesn't necessarily change the core philosophy.&lt;br&gt;
Traditionally, in a multithreading environment, you have multiple hardware threads that each execute work in true parallel.&lt;br&gt;
This number is limited by your CPU, usually from 4 to 24 threads on modern desktops (half as many cores, but hyperthreading!).&lt;br&gt;
On the OS level, the number is much greater. But those aren't truly parallel threads. The OS performs context switching between threads,&lt;br&gt;
essentially giving each thread a slice of time to execute. For example, if you have 1 thread that takes 1 second to execute,&lt;br&gt;
you could split that up into 1000 OS threads that each take 1 ms to execute. However, your CPU doesn't actually have 1000 hardware threads,&lt;br&gt;
so the OS gives each thread a slice of time to execute.&lt;/p&gt;

&lt;p&gt;Coroutines are slightly different. Forgetting about Boost.Asio for a moment, C++ coroutines have nothing to do with threads.&lt;br&gt;
They don't necessarily enable parallel work, but they do enable asynchronous and &lt;strong&gt;concurrent&lt;/strong&gt; work.&lt;br&gt;
Coroutines are a lightweight language construct in C++, not an OS or hardware level feature.&lt;/p&gt;

&lt;p&gt;A popular analogy for coroutines is a chef in a kitchen. When a chef prepares a pizza, he must prepare the dough and ingredients first,&lt;br&gt;
but then he puts it all into the oven. Once the oven goes, the chef waits for 10 minutes for the pizza to cook. Then, he takes it out and gives it to the waiter.&lt;br&gt;
This is a traditional, single-threaded approach. There is a blocking event in the middle, waiting for the pizza to cook.&lt;br&gt;
There is a way to optimize this even without threads. We limit ourselves to one chef, so that means only 1 thread.&lt;br&gt;
When the chef puts the pizza, he can simultaneously start working on the next pizza. This can enable him to do orders of magnitude more work than before.&lt;br&gt;
All without parallelism.&lt;/p&gt;

&lt;p&gt;This is the essence of coroutines. The keyword &lt;code&gt;co_await&lt;/code&gt; allows you to suspend the coroutine until some asynchronous event occurs.&lt;br&gt;
Not only does it suspend the coroutine, it signals that we can start working on some other task until we receive the value from &lt;code&gt;co_await&lt;/code&gt;.&lt;br&gt;
This is analogous to the chef working on the next pizza after putting the pizza in the oven (the chef co_awaits on the result from the oven).&lt;/p&gt;

&lt;p&gt;The other coroutine keyword is &lt;code&gt;co_yield&lt;/code&gt;, which we won't need here. It is similar to &lt;code&gt;co_return&lt;/code&gt;, except you can resume a &lt;code&gt;co_yield&lt;/code&gt; later.&lt;br&gt;
Imagine you have a for-loop, each iteration yields a value, but you can resume the for-loop if you wish after receiving a value.&lt;br&gt;
&lt;code&gt;co_yield&lt;/code&gt; is used commonly in generators, which we won't need to make. There is the aforementioned &lt;code&gt;co_return&lt;/code&gt;, which&lt;br&gt;
returns a value from a coroutine.&lt;/p&gt;

&lt;p&gt;Specific to Boost.Asio, there is &lt;code&gt;co_spawn&lt;/code&gt;, which spawns a new coroutine (techinically, it schedules a coroutine on an executor).&lt;br&gt;
You may be wondering why we can't do this through regular C++.&lt;br&gt;
C++'s coroutines are just a language feature with syntax and compiler hooks. The way to "spawn" a coroutine is to just call the function,&lt;br&gt;
but without a schedular, nothing drives or resumes it.&lt;br&gt;
However, there is no higher-level orchestration. What if the coroutine starts in a suspended state?&lt;br&gt;
What about scheduling coroutines? What if we want to wait for multiple coroutines to finish? What if we want to cancel a coroutine?&lt;br&gt;
What about thread safety?&lt;br&gt;
These are all things that Boost.Asio provides.&lt;br&gt;
Asio is the driver with &lt;code&gt;co_spawn&lt;/code&gt; and &lt;code&gt;io_context&lt;/code&gt; that orchestrates the coroutines. &lt;code&gt;io_context&lt;/code&gt; is the main event loop. It has all the state and controls everything about the coroutines.&lt;/p&gt;

&lt;p&gt;So, you may be wondering why we are doing asynchronous programming with Coroutines rather than parallel programming with threads.&lt;br&gt;
Asynchronous is far more efficient for I/O bound work, which a network server is bound to.&lt;br&gt;
In general, when you have 1 large task that can be broken down into smaller subtasks, use threads (CPU-heavy tasks).&lt;br&gt;
If you have various different small tasks that aren't particularly connected, especially involving lots of I/O,&lt;br&gt;
or you're bound by memory: use asynchronous programming.&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting into the Code
&lt;/h2&gt;

&lt;p&gt;We'll be building on the same code from &lt;a href="https://amn.sh/blog/2025-12-14-http-server-in-cpp" rel="noopener noreferrer"&gt;part 1&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We'll start by making the tcp_server asynchronous.&lt;/p&gt;

&lt;p&gt;src/tcp_server.cpp&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// existing code&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;coroutine&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// existing code&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;tcp_server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// The normal accept loop, but now as a coroutine&lt;/span&gt;
    &lt;span class="c1"&gt;// We explicitly use m_IoContext here; alternatively, we could provide a specific executor&lt;/span&gt;
    &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;co_spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m_IoContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;]()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;awaitable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(;;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="c1"&gt;// the actual accepting of sockets&lt;/span&gt;
                &lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m_IoContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="c1"&gt;// suspends this coroutine until a client connects and returns control to m_IoContext&lt;/span&gt;
                &lt;span class="k"&gt;co_await&lt;/span&gt; &lt;span class="n"&gt;m_Acceptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;async_accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;use_awaitable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="c1"&gt;// launches a new coroutine for each connection&lt;/span&gt;
                &lt;span class="c1"&gt;// ownership of the socket must be transferred to the coroutine, otherwise the lifetime of the socket would be undefined&lt;/span&gt;
                &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;co_spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m_IoContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;detached&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;detached&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// detached allows us to fire-and-forget, with no result or exception being captured&lt;/span&gt;

        &lt;span class="c1"&gt;// this starts processing the coroutines&lt;/span&gt;
        &lt;span class="c1"&gt;// blocks the calling thread and runs until no more work exists&lt;/span&gt;
        &lt;span class="n"&gt;m_IoContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// existing code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A question you may have is what is &lt;code&gt;boost::asio::use_awaitable&lt;/code&gt;. Well, awaitables essentially allow you to replace callbacks with coroutines.&lt;br&gt;
Old Asio code looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;async_read_some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// a callback function to handle the data after it is done reading&lt;/span&gt;
    &lt;span class="p"&gt;[](&lt;/span&gt;&lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;error_code&lt;/span&gt; &lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;handle_data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But with coroutines, we essentially want an item to be returned that we can &lt;code&gt;co_await&lt;/code&gt; on.&lt;br&gt;
So, modern Asio with awaitables looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;co_await&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;async_read_some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;use_awaitable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note also that we don't have good error handling here. I'll leave that as an exercise for the reader. It really isn't that hard, just some try/catch blocks.&lt;br&gt;
Just know that when a detached coroutine throws, the program terminates.&lt;/p&gt;

&lt;p&gt;Now that &lt;code&gt;server.run()&lt;/code&gt; is blocking and does an infinite loop, we no longer need the infinite loop in main.cpp.&lt;/p&gt;

&lt;p&gt;src/main.cpp&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// existing code&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;tcp_server&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// existing code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we've established our main loop, it's time to get back to the tcp_server and make parsing asynchronous!&lt;/p&gt;

&lt;h3&gt;
  
  
  Asynchronous Parsing
&lt;/h3&gt;

&lt;p&gt;We just have to replace the blocking &lt;code&gt;read_some&lt;/code&gt; with &lt;code&gt;async_read_some&lt;/code&gt;. If you added CORS handling, you'll need to do a &lt;code&gt;co_return&lt;/code&gt; from there.&lt;/p&gt;

&lt;p&gt;src/tcp_server.cpp&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// existing code&lt;/span&gt;

&lt;span class="c1"&gt;// we need to change the return type to be an awaitable too&lt;/span&gt;
&lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;awaitable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HttpRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;streambuf&lt;/span&gt; &lt;span class="n"&gt;request_buffer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// we suspend this coroutine and let some other work happen until we finish reading the request&lt;/span&gt;
    &lt;span class="k"&gt;co_await&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;async_read_until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;use_awaitable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="c1"&gt;// we're only parsing the request line&lt;/span&gt;
    &lt;span class="c1"&gt;// if you wanted to parse headers, use "\r\n\r\n"&lt;/span&gt;

    &lt;span class="c1"&gt;// existing code&lt;/span&gt;

    &lt;span class="c1"&gt;// replace line: http::response_handler::dispatch(socket, request); with:&lt;/span&gt;

    &lt;span class="c1"&gt;// we also suspend execution here until we finish dispatching, letting other work happen in the meantime&lt;/span&gt;
    &lt;span class="k"&gt;co_await&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;response_handler&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// existing code&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// existing code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it! We've made parsing asynchronous. Now, we need to make dispatching asynchronous.&lt;/p&gt;

&lt;h2&gt;
  
  
  Asynchronous Dispatching
&lt;/h2&gt;

&lt;p&gt;First, we need to make the &lt;code&gt;dispatch&lt;/code&gt; function return an awaitable.&lt;/p&gt;

&lt;p&gt;src/response_handler.h&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// existing code&lt;/span&gt;
&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;response_handler&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;awaitable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// existing code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let's modify the implementation.&lt;/p&gt;

&lt;p&gt;src/response_handler.cpp&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// existing code&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;response_handler&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;awaitable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;path_handlers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Not Found"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Not Found"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;co_await&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// first time we've seen co_return. It just allows us to return from a coroutine&lt;/span&gt;
            &lt;span class="c1"&gt;// implicity returns void (same as coreturn void)&lt;/span&gt;
            &lt;span class="k"&gt;co_return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;co_await&lt;/span&gt; &lt;span class="n"&gt;path_handlers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;co_await&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// we don't need to specify co_return here, it is implicit&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We escape execution at a few steps. Those are when writing to a socket and when executing the path handler function.&lt;br&gt;
We escape the coroutine when writing to a socket because writing to a socket is asynchronous itself (blocking normally),&lt;br&gt;
so we can just hand execution off to something else (io_context) until we're done.&lt;br&gt;
We also escape the coroutine when executing the path handler function because the path handler function is also asynchronous.&lt;br&gt;
Although path handling is not inherently asynchronous like writing to a socket, the path handler may have async code inside it.&lt;/p&gt;

&lt;p&gt;Now, we need to actually make the &lt;code&gt;HttpResponse.write()&lt;/code&gt; and path handlers asynchronous.&lt;/p&gt;

&lt;p&gt;src/response_handler.cpp&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// existing code&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;HttpResponse&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;private:&lt;/span&gt;
        &lt;span class="c1"&gt;// existing code&lt;/span&gt;
    &lt;span class="nl"&gt;public:&lt;/span&gt;
        &lt;span class="c1"&gt;// existing code (set_* functions)&lt;/span&gt;

        &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;awaitable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// existing code&lt;/span&gt;

            &lt;span class="c1"&gt;// we suspend execution until we finish writing the response&lt;/span&gt;
            &lt;span class="k"&gt;co_await&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;async_write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;use_awaitable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;path_handler_fn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;awaitable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;unordered_map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path_handler_fn&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;path_handlers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[](&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;awaitable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;{}.&lt;/span&gt;&lt;span class="n"&gt;set_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;405&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Method Not Allowed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Method Not Allowed"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="k"&gt;co_return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="c1"&gt;// I'll get back to stream files in a bit&lt;/span&gt;
                &lt;span class="c1"&gt;// For now, imagine it as being able to use a file with the same API as a socket&lt;/span&gt;
                &lt;span class="c1"&gt;// i.e., you can async_read and async_write to it like a socket&lt;/span&gt;
                &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;stream_file&lt;/span&gt; &lt;span class="nf"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_executor&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

                &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;error_code&lt;/span&gt; &lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test_client/client.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;stream_file&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;read_only&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;{}.&lt;/span&gt;&lt;span class="n"&gt;set_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Internal Server Error"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to open client.html&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ec&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
                    &lt;span class="k"&gt;co_return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seek&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;stream_file&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;seek_end&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seek&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;stream_file&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;seek_set&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'\0'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="k"&gt;co_await&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;async_read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                    &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;use_awaitable&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OK"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"text/html; charset=utf-8"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="k"&gt;co_return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="s"&gt;"/time"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[](&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;awaitable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;405&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Method Not Allowed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Method Not Allowed"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="k"&gt;co_return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;

                &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;chrono&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;system_clock&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;timeString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:%Y-%m-%d %H:%M:%S}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OK"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="k"&gt;co_return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// existing code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A few unique things you may notice. First, we are actually using &lt;code&gt;co_return&lt;/code&gt; to return values. In this case, awaitables&lt;br&gt;
of type &lt;code&gt;HttpResponse&lt;/code&gt; are returned from the path handlers.&lt;/p&gt;

&lt;p&gt;Second, we are using &lt;code&gt;boost::asio::stream_file&lt;/code&gt; to read from a file. This is a modern feature of Boost.Asio that allows you to treat a file as a socket.&lt;br&gt;
This makes asynchronous File I/O a breeze. You may get issues with including it in the build, though.&lt;br&gt;
On Windows, you may need to add this macro to your build system compile definitions: &lt;code&gt;_WIN32_WINNT=0x0A00&lt;/code&gt;.&lt;br&gt;
On Linux, you may need to link to &lt;code&gt;liburing&lt;/code&gt;. I'll leave these as exercises for the reader.&lt;br&gt;
If you can't figure it out, look at &lt;a href="https://github.com/ArmaanCPro/aychTTP/blob/main/CMakeLists.txt" rel="noopener noreferrer"&gt;my build system&lt;/a&gt; or post a comment at the bottom of this page.&lt;/p&gt;
&lt;h2&gt;
  
  
  Templating Engine
&lt;/h2&gt;

&lt;p&gt;Firstly, we'll be using &lt;a href="https://github.com/pantor/inja" rel="noopener noreferrer"&gt;Inja&lt;/a&gt; for templating.&lt;br&gt;
We'll be using nlohmann's JSON library for providing data to Inja.&lt;br&gt;
You'll see what that means shortly.&lt;br&gt;
Also, make sure you link your executable to Inja and nlohmann's JSON library in your build system.&lt;/p&gt;

&lt;p&gt;With Inja, templating is really quite easy.&lt;br&gt;
If you don't know what templating is, it's essentially a way to programmatically generate HTML.&lt;br&gt;
Say you had an array in C++ that you wanted to transform into a list in HTML.&lt;br&gt;
You could write a loop in C++ to generate the HTML, but that would be error-prone and inefficient.&lt;br&gt;
Instead, we can use a templating engine to generate the HTML for us. The engine has knowledge of C++ structures.&lt;br&gt;
Currently, we're building HTML ourselves. For example, in the &lt;code&gt;/time&lt;/code&gt; path handler, we pass a raw string.&lt;br&gt;
What if we wanted to add HTML elements like bold text or italicized text to that response?&lt;br&gt;
We could manually write the HTML using C++ strings or have the templating engine do it for us.&lt;/p&gt;

&lt;p&gt;Inja takes in data as JSON. Say we have the following template:&lt;br&gt;
&lt;code&gt;{{ time }}&lt;/code&gt;. Time could be anything, really. Inja recognizes through the &lt;code&gt;{{ }}&lt;/code&gt; syntax that it should be replaced with some data.&lt;br&gt;
We can pass data to Inja using JSON. We have a JSON key &lt;code&gt;time&lt;/code&gt; that has a value of the current time.&lt;br&gt;
Then, we can render to a &lt;code&gt;std::string&lt;/code&gt; using Inja via &lt;code&gt;inja::render()&lt;/code&gt;.&lt;br&gt;
We could give the template to Inja as a raw string, or we could pass it a file path.&lt;br&gt;
For now, we'll just pass it a raw string.&lt;/p&gt;

&lt;p&gt;Navigate to the &lt;code&gt;/time&lt;/code&gt; path handler function:&lt;/p&gt;

&lt;p&gt;src/response_handler.cpp&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// existing code&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"/time"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[](&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;awaitable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// existing code&lt;/span&gt;

        &lt;span class="c1"&gt;// replace the manual timeString stuff with this:&lt;/span&gt;
        &lt;span class="n"&gt;nlohmann&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"time"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:%Y-%m-%d %H:%M:%S}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;chrono&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;system_clock&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

        &lt;span class="c1"&gt;// we don't need an env for our use-case&lt;/span&gt;
        &lt;span class="c1"&gt;// but it is good to have one in case you want to render a file or something else&lt;/span&gt;
        &lt;span class="n"&gt;Inja&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{{ time }} with ❤️ from C++"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OK"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// this is still technically plain-text, not html, so we don't need to change the "Content-Type" header&lt;/span&gt;
        &lt;span class="c1"&gt;// if we had html elements, we would need to change it to "text/html; charset=utf-8"&lt;/span&gt;

        &lt;span class="k"&gt;co_return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The JSON is called vm because it is the view-model. It's the data that Inja will use to render the template.&lt;br&gt;
It gives Inja the view into our data. It is also, at the same time, the model of the data itself.&lt;br&gt;
It controls the shape and type of data.&lt;/p&gt;

&lt;p&gt;At this point, we have a fully asynchronous server with a templating engine!&lt;/p&gt;

&lt;p&gt;This is a fully featured C++ HTTP server.&lt;br&gt;
Truly, the vast majority of features left for implementation are CORS handling (which is quite easy)&lt;br&gt;
and architectural changes to make the server more scalable (not just a jump table of lambdas for handlers).&lt;br&gt;
These are all QoL, the main foundations of the server are done and dusted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We've made a fully asynchronous HTTP server in C++.&lt;br&gt;
What does that mean?&lt;br&gt;
It means it can scale to potentially millions of concurrent connections.&lt;br&gt;
We don't even have any multithreading in play. Sure, we could use a thread pool to drive the io_context, but we're running it on a single thread.&lt;br&gt;
Multithreading &lt;em&gt;may&lt;/em&gt; introduce performance gains, but not as much as asynchronous programming.&lt;br&gt;
Look into how you can use thread pools with Boost.Asio and io_context if you want to learn more.&lt;/p&gt;

&lt;p&gt;The templating engine gives us a way to easily serve HTML from the server without having to manually form HTML&lt;br&gt;
from C++ strings. Moreover, we've given the server some structure in how it manages data: JSON.&lt;br&gt;
We don't necessarily need to use JSON as the model of our data, but having it as the view is certainly useful.&lt;br&gt;
We could represent our data however we want.&lt;/p&gt;

&lt;p&gt;Now, don't confuse our asynchronous server with asynchronous APIs.&lt;br&gt;
Asynchronous APIs technically don't need to even execute on an asynchronous backend.&lt;br&gt;
Basically, all an asynchronous API does is respond to the client saying that it will give back the true value at some point in the future.&lt;br&gt;
Then, later, it sends another request with the final value.&lt;br&gt;
This can be done through webhooks, emails, having the client poll the server on an interval, etc.&lt;br&gt;
You could hobble together an asynchronous API using our current server, or even the one from part 1.&lt;/p&gt;

&lt;p&gt;Our server isn't a production-grade HTTP server.&lt;br&gt;
But you can certainly take it there using this as a solid foundation.&lt;/p&gt;

&lt;p&gt;Some things for further improvement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The jump table is intentionally simple; real servers use structured routers, middleware chains, and prefix matching&lt;/li&gt;
&lt;li&gt;The server doesn't handle errors very well.&lt;/li&gt;
&lt;li&gt;No logging&lt;/li&gt;
&lt;li&gt;No tests&lt;/li&gt;
&lt;li&gt;Authentication? (not inherently HTTP, but useful in a web backend)&lt;/li&gt;
&lt;li&gt;Parsing the headers and body of an HttpRequest

&lt;ul&gt;
&lt;li&gt;Handling partial reads and malformed requests&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Backpressure and capping concurrent work (not just fire-and-forget)&lt;/li&gt;

&lt;li&gt;Optimizing hot code paths&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>cpp</category>
      <category>networking</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Building an HTTP Server in C++: From TCP to HTMX (Part 1)</title>
      <dc:creator>Armaan Chahal</dc:creator>
      <pubDate>Sun, 14 Dec 2025 00:12:00 +0000</pubDate>
      <link>https://forem.com/armaancpro/tcp-to-http-in-c-to-serve-htmx-1foi</link>
      <guid>https://forem.com/armaancpro/tcp-to-http-in-c-to-serve-htmx-1foi</guid>
      <description>&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Welcome. We're gonna talk about how web servers actually work, in C++, without magic.&lt;br&gt;
If you want to skip the conceptual lore dump, go right ahead to the code sections.&lt;br&gt;
On the topic of theory vs practice, here's a phenomenal quite by Donald Knuth:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you find that you're spending almost all your time on theory, start turning some attention to practical things; it will improve your theories.&lt;br&gt;
If you find that you're spending almost all your time on practice, start turning some attention to theoretical things; it will improve your practice.&lt;/p&gt;

&lt;p&gt;---Donald Knuth&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This article walks through building a minimal HTTP/1.1 server directly on top of TCP using Boost.Asio.&lt;br&gt;
The focus is not production readiness, but understanding how modern asynchronous C++ maps to real web protocols.&lt;br&gt;
You don't need to be super comfortable with C++ or networking,&lt;br&gt;
but it would certainly help. If you're trying to transition to C++ from a higher-level language, props.&lt;/p&gt;

&lt;p&gt;If you want to skip straight to a concurrent HTTP server with templating, read &lt;a href="https://www.amn.sh/blog/2025-12-15-http-server-in-cpp-part2" rel="noopener noreferrer"&gt;part 2&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  HTTP in C++... why?
&lt;/h2&gt;

&lt;p&gt;The first question anyone with sense would pose, upon hearing of someone writing an HTTP server in C++, is why?&lt;br&gt;
Perhaps with a few added exclamation points.&lt;/p&gt;

&lt;p&gt;Now, there are a few reasons one would get started with such a feat. Primarily: learning!&lt;br&gt;
For learning purposes, there is no better way to understand HTTP and how the web truly works than by writing an HTTP server in a language where the web isn't a first-class citizen.&lt;br&gt;
(Or at least, where the web wasn't meant to be first-class...)&lt;/p&gt;

&lt;p&gt;Moreover, there truly do come times when a very high-performance backend is necessary. It doesn't necessarily have to be for a website, though that is a common use-case.&lt;br&gt;
If you want performance, it just isn't feasible with JavaScript or other high-level languages. For such an endeavour, I would honestly recommend using a language that has more support for HTTP in it's standard library.&lt;br&gt;
For example, Go and Rust. Now, C++ is my bread and butter, but even the people on the standards committee can agree that networking is one place where C++ is lacking.&lt;br&gt;
If you still want to use C++ for a production-grade application, check out libraries like &lt;a href="https://github.com/drogonframework/drogon" rel="noopener noreferrer"&gt;Drogon&lt;/a&gt; or &lt;a href="https://github.com/boostorg/beast" rel="noopener noreferrer"&gt;Boost.Beast&lt;/a&gt;.&lt;br&gt;
They provide higher-level abstractions for HTTP (so you don't actually have to write an HTTP server from TCP sockets).&lt;/p&gt;
&lt;h2&gt;
  
  
  Where Does that Leave Us?
&lt;/h2&gt;

&lt;p&gt;We're gonna use TCP sockets. There are certainly a few ways you can do that in C++, most people will point you to 3 different methods:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;OS-specific sockets libraries (i.e. WinSock, POSIX/Berkeley sockets)&lt;/li&gt;
&lt;li&gt;libuv (What Nodejs uses)&lt;/li&gt;
&lt;li&gt;Boost.Asio&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We're going to use Boost.Asio. From now on, I'm going to refer to Boost.Asio as &lt;em&gt;Asio&lt;/em&gt;, but don't get confused with the older, standalone Asio library (whenever I refer to Asio, I mean Boost.Asio).&lt;/p&gt;

&lt;p&gt;Asio is distributed under the generous &lt;strong&gt;Boost Software License&lt;/strong&gt;, which is quite similar to other popular licenses like the MIT License, Apache, BSD, etc. Check it out &lt;a href="https://www.boost.org/doc/user-guide/bsl.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Why did I choose Boost.Asio over OS-specific options? Well, it has a nicer API and is cross-platform.&lt;br&gt;
And why over libuv? For no particular reason other than I was already familiar with Asio and wasn't with libuv. Both are great libraries, and I would suggest you look at libuv for a wider perspective afterward.&lt;/p&gt;

&lt;p&gt;What other dependencies will we need? In the future, we're going to need &lt;em&gt;Inja&lt;/em&gt; and a JSON library. That's for a templating engine, like Jinja2, Go/Templ, etc.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Theory
&lt;/h3&gt;

&lt;p&gt;We all love whiteboard sessions, right? No... just me? Whiteboarding is both good and bad. I won't get into that here, but it is necessary to lay down some fundamentals of HTTP before we start coding the thing.&lt;/p&gt;

&lt;p&gt;Firstly, let's define our client. Who will actually be sending the requests? We could write our own client in C++ or a higher-level language, but if you read the title, you already know that our client will be &lt;a href="https://htmx.org/" rel="noopener noreferrer"&gt;HTMX&lt;/a&gt;.&lt;br&gt;
HTMX is a great library; if you're unfamiliar with it, it is essentially raw HTML, but you can attach HTTP requests to any element, not just &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;form&amp;gt;&lt;/code&gt;.&lt;br&gt;
If we were to write an HTTP client in C++, that would be super boring. All we would see would be console logs like "REQUEST SENT!" and "RESPONSE SENT!" and "RESPONSE RECEIEVED!"&lt;/p&gt;

&lt;p&gt;Instead, we can have a nice frontend in our browser! At the end of the day, the browser is doing the heavy lifting for the client-side application. But that means all we will have to write is some HTMX code.&lt;/p&gt;
&lt;h4&gt;
  
  
  HTTP
&lt;/h4&gt;

&lt;p&gt;Now, let's define HTTP itself. An HTTP request is a text-based and consists of a few different parts. Well, technically bodies are binary and headers &lt;em&gt;may&lt;/em&gt; encode data.&lt;br&gt;
That means that we don't need any fancy serialization or deserialization logic. To be clear, we're going to write a server for HTTP/1.1, not HTTP/2.&lt;br&gt;
That just makes life a little easier for us. To understand HTTP/2, you need to first understand HTTP/1.1.&lt;br&gt;
HTTP is just a protocol, like TCP and UDP. It stands for Hypertext Transfer Protocol, so you can probably infer it has something to do with HTML.&lt;br&gt;
That intuition is correct, as HTTP is most commonly used in websites (though it's not limited to that).&lt;/p&gt;

&lt;p&gt;HTTP Requests have a few main parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Method&lt;/li&gt;
&lt;li&gt;Path&lt;/li&gt;
&lt;li&gt;Version&lt;/li&gt;
&lt;li&gt;Headers&lt;/li&gt;
&lt;li&gt;Body&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;HTTP Responses are slightly different:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Version&lt;/li&gt;
&lt;li&gt;Status Code&lt;/li&gt;
&lt;li&gt;Status Message&lt;/li&gt;
&lt;li&gt;Headers&lt;/li&gt;
&lt;li&gt;Body&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The body and headers are optional in both requests and responses. An example request is this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;developer.mozilla.org&lt;/span&gt;
&lt;span class="na"&gt;Accept-Language&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;fr&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a sample response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;span class="na"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Sat, 09 Oct 2010 14:28:02 GMT&lt;/span&gt;
&lt;span class="na"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Apache&lt;/span&gt;
&lt;span class="na"&gt;Last-Modified&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Tue, 01 Dec 2009 20:18:22 GMT&lt;/span&gt;
&lt;span class="na"&gt;ETag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"51142bc1-7449-479b075b2891b"&lt;/span&gt;
&lt;span class="na"&gt;Accept-Ranges&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bytes&lt;/span&gt;
&lt;span class="na"&gt;Content-Length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;29769&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;text/html&lt;/span&gt;

&lt;span class="cp"&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;… (here come the 29769 bytes of the requested web page)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this scenario, the user asks for a GET request to the path "/", essentially requesting the index.html file, which is the primary HTML document the browser is meant to show. The server then sends back raw HTML within the response body.&lt;br&gt;
The headers simply contain additional details regarding the request or response; these are sometimes needed, such as Content-Type and Content-Length, especially when a body is present.&lt;/p&gt;

&lt;p&gt;Yes, I got both of these from the phenomenal &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/Overview" rel="noopener noreferrer"&gt;HTTP docs by mozilla&lt;/a&gt;. Definitely give them a read for more in-depth information about the HTTP protocol.&lt;/p&gt;

&lt;p&gt;HTTP isn't magic, and if you still have some questions, they will certainly get dispelled once we reach the coding section. Or ask them at the bottom of this page!&lt;/p&gt;
&lt;h4&gt;
  
  
  TCP
&lt;/h4&gt;

&lt;p&gt;So, Boost.Asio has no clue about HTTP. All it knows about is TCP (or UDP, but we HTTP requests need to be reliable, hence we use TCP).&lt;br&gt;
Boost.Asio will handle all the low-level details about TCP. It delegates even lower-level TCP details like the 3-way handshake to the OS.&lt;br&gt;
Boost.Asio exposes to us a TCP socket, from which we can read data (i.e., on the server we read the request) and write data (we write back to the client with our HTTP Response).&lt;br&gt;
This dynamic enables us to worry solely about the HTTP data itself and not about the low-level TCP connections that actually underpin HTTP.&lt;/p&gt;

&lt;p&gt;If you want to learn more about TCP and fundamental networking in general, I recommend the book &lt;a href="https://www.amazon.com/TCP-Illustrated-Protocols-Addison-Wesley-Professional/dp/0321336313?crid=5GD1XQGNTN95&amp;amp;dib=eyJ2IjoiMSJ9.vT1aaq_MECo7C_Rc8QXTO2ViERVDXTXEw7blI3INbKdonqpoca7yvF_1uh1F8E3IRIi7P9mZ6cQb64np-YNatX4Hnukao1LLsedp7Rpi5dhEhNLh8V17RP-jJwQKqzHQyI-aZFpliQIo8vKK3f0YDOL1Ld5qIeTr8NHtBeT-K7_uC3wUdDBXo0wMIOrH00HuXaSwD8MZkrgkCToUeCdPJ5yDGJvSCnvCMlfXA26LD5I.eAA72G7gOb1ZT_hOOF2Oc5U1fi2KDeiGpNboLTOqPYQ&amp;amp;dib_tag=se&amp;amp;keywords=tcp%2Fip+illustrated&amp;amp;qid=1765769052&amp;amp;s=books&amp;amp;sprefix=tcp%2Fip+illustrate%2Cstripbooks%2C151&amp;amp;sr=1-1" rel="noopener noreferrer"&gt;TCP/IP Illustrated&lt;/a&gt;.&lt;br&gt;
You only really need Volume 1. Whether you get the first or second edition doesn't matter.&lt;/p&gt;
&lt;h3&gt;
  
  
  From Humble Beginnings
&lt;/h3&gt;

&lt;p&gt;We'll write our HTMX client now. Just so that we can get started. If you want an idea about the project structure, here's a link to the &lt;a href="https://github.com/ArmaanCPro/aychTTP/tree/5cd9ba7e4c2d037f03f3588880674b90944a3df3" rel="noopener noreferrer"&gt;final project&lt;/a&gt;.&lt;br&gt;
That is an old commit, but it's probably as far as we'll get to in this post. Check the main branch's HEAD for some more features.&lt;/p&gt;

&lt;p&gt;Let's start with some HTML.&lt;/p&gt;

&lt;p&gt;test_client/client.html&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;HTMX Client&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;button&amp;gt;&lt;/span&gt;
        Get Time
    &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"time"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Waiting for button click&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neat, right? No? Oh... you're wondering where the HTMX is?&lt;br&gt;
Wait, wait, I see it!&lt;/p&gt;

&lt;p&gt;test_client/client.html&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;...
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;HTMX Client&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdn.jsdelivr.net/npm/htmx.org@2.0.8/dist/htmx.min.js"&lt;/span&gt; &lt;span class="na"&gt;integrity=&lt;/span&gt;&lt;span class="s"&gt;"sha384-/TgkGk7p307TH7EXJDuUlgG3Ce1UVolAOFopFekQkkXihi5u/6OCvVKyz1W+idaz"&lt;/span&gt; &lt;span class="na"&gt;crossorigin=&lt;/span&gt;&lt;span class="s"&gt;"anonymous"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
...

    &lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;hx-get=&lt;/span&gt;&lt;span class="s"&gt;"/time"&lt;/span&gt; &lt;span class="na"&gt;hx-target=&lt;/span&gt;&lt;span class="s"&gt;"#time"&lt;/span&gt; &lt;span class="na"&gt;hx-trigger=&lt;/span&gt;&lt;span class="s"&gt;"click"&lt;/span&gt; &lt;span class="na"&gt;hx-swap=&lt;/span&gt;&lt;span class="s"&gt;"innerHTML"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        Get Time
    &lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There we go. Now, we inject HTMX via a CDN, and we hook up the button to some HTML events. We're basically saying that when the button is clicked, sent a GET request to the path '/time' and swap the innerHTML of the element with id time.&lt;br&gt;
That element is our div. The innerHTML of the div is just the text inside it.&lt;/p&gt;

&lt;p&gt;Straightforward, I know, but enough to get us started!&lt;/p&gt;
&lt;h4&gt;
  
  
  Onto C++
&lt;/h4&gt;

&lt;p&gt;Now, make sure your C++ build system is linking to Boost.Asio and is set to C++23 (you may be able to get by with older versions, but I haven't tested them). Again, if you want more info on the build system, see the &lt;a href="https://github.com/ArmaanCPro/aychTTP/tree/5cd9ba7e4c2d037f03f3588880674b90944a3df3" rel="noopener noreferrer"&gt;GitHub repo I linked earlier&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's just start in the main function to see how we can actually use Asio.&lt;/p&gt;

&lt;p&gt;src/main.cpp&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;boost/asio.hpp&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;print&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;constexpr&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000u&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;io_context&lt;/span&gt; &lt;span class="n"&gt;io_context&lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;
        &lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;acceptor&lt;/span&gt; &lt;span class="nf"&gt;acceptor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;io_context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;v4&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt; &lt;span class="c1"&gt;// the acceptor connects to a port and waits for a socket&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(;;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;io_context&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// the socket itself&lt;/span&gt;
            &lt;span class="n"&gt;acceptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// blocking function call that waits for a connection&lt;/span&gt;

            &lt;span class="c1"&gt;// this is intentionally blocking, we'll get to async code in part 2&lt;/span&gt;

            &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hi from server"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;error_code&lt;/span&gt; &lt;span class="n"&gt;ignored_error&lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt; &lt;span class="c1"&gt;// we ignore the error of the write&lt;/span&gt;
            &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;ignored_error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// this writes a buffer to the socket, in this case just a string&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;what&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, this is no HTTP, but interestingly enough, we'll have a very similar code flow for the actual HTTP server. We wait for a socket to arrive to our designated port, then read from it, then write to it!&lt;br&gt;
Currently, we're not doing any reading from the socket, but we will soon enough.&lt;/p&gt;

&lt;p&gt;Now that we have the basic understanding of how we can actually do networking stuff, let's consider what our http server will look like in code.&lt;/p&gt;
&lt;h4&gt;
  
  
  Project Design
&lt;/h4&gt;

&lt;p&gt;We start at our HTMX client, the browser. That sends an HttpRequest to our server.&lt;/p&gt;

&lt;p&gt;The server itself is composed of 4 layers.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;TCP Accept/Connect Layer (&lt;code&gt;acceptor.accept(socket);&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;HTTP Request Parser&lt;/li&gt;
&lt;li&gt;Router/Dispatcher&lt;/li&gt;
&lt;li&gt;Handler functions&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We'll go into more detail as we get to coding each part, but these are the 4 major parts of our project.&lt;/p&gt;

&lt;p&gt;At layer 1, it's the same code we already covered, we wait for a TCP socket connection.&lt;br&gt;
At layer 2, we parse the HTTP Request into 3 distinct fields for now: method, path, version. We don't necessarily need to keep track of the version, as we know it's going to be HTTP/1.1, but it doesn't hurt.&lt;br&gt;
At layer 3, we see dispatch to the proper handler based on the path in the http request.&lt;br&gt;
At layer 4, the handler functions will do some logic, build an HTTP Response, and eventually write them back to the socket.&lt;/p&gt;

&lt;p&gt;Pretty simple, right?&lt;/p&gt;
&lt;h4&gt;
  
  
  Layer 1: Connections
&lt;/h4&gt;

&lt;p&gt;Let's make a few new files for the sake of organization. First, though, let's modify main.cpp.&lt;/p&gt;

&lt;p&gt;src/main.cpp&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;print&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"tcp_server.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="c1"&gt;// rest of the code...&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;tcp_server&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// we will make this class soon&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(;;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// can you imagine what server.run() will do?&lt;/span&gt;
            &lt;span class="c1"&gt;// again, intentionally blocking, we'll get to concurrency in part 2&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// rest of the code...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, a new file:&lt;/p&gt;

&lt;p&gt;src/tcp_server.h&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#pragma once
&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;boost/asio.hpp&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;cstdint&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// this struct represents all the data we'll parse out of the HttpRequest coming from the client&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;HttpRequest&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// yes, these aren't string_views; these need to own the strings&lt;/span&gt;
        &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;tcp_server&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;public:&lt;/span&gt;
        &lt;span class="n"&gt;tcp_server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// call this to actually run the server for 1 single TCP connection, hence the loop in main.cpp&lt;/span&gt;
        &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nl"&gt;private:&lt;/span&gt;
        &lt;span class="c1"&gt;// look familiar?&lt;/span&gt;
        &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;io_context&lt;/span&gt; &lt;span class="n"&gt;m_IoContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;acceptor&lt;/span&gt; &lt;span class="n"&gt;m_Acceptor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So far, pretty self-explanatory. The tcp_server will handle layers 1 and 2, of connection and parsing.&lt;/p&gt;

&lt;p&gt;Let's start with the run method, which we will define in a new file:&lt;/p&gt;

&lt;p&gt;src/tcp_server.cpp&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"tcp_server.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;print&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;literals&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// just some niceties&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;tcp_server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;tcp_server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint32_t&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;// m_IoContext is default constructed before m_Acceptor automatically&lt;/span&gt;
        &lt;span class="n"&gt;m_Acceptor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m_IoContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;v4&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;static_cast&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;port_type&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt; &lt;span class="c1"&gt;// the constructor for acceptor technically doesn't take in a uint32_t&lt;/span&gt;
    &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;tcp_server&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m_IoContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;m_Acceptor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// we'll get to this soon&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing extraordinary yet, we've just reorganized the code we had before. But trust me, it's finally about to start to get interesting.&lt;/p&gt;

&lt;h4&gt;
  
  
  Layer 2: Parsing
&lt;/h4&gt;

&lt;p&gt;Parsing HTTP, for our case so far, is surprisingly easy. We don't need to worry about headers or a body for our purposes today.&lt;br&gt;
All we care about is the stuff defined in HttpRequest in &lt;code&gt;tcp_server.h&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In case you're wondering what &lt;code&gt;parse(std::move(socket));&lt;/code&gt; was doing earlier, here we are.&lt;/p&gt;

&lt;p&gt;src/tcp_server.cpp&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"response_handler.h"&lt;/span&gt;&lt;span class="c1"&gt; // we'll get here later&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;span class="c1"&gt;// existing code...&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="c1"&gt;// a C++ anonymous namespace&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// why do we take socket by value you may be wondering?&lt;/span&gt;
        &lt;span class="c1"&gt;// well, once we get to concurrency, the parser needs to take ownership of the socket for lifetime's sake&lt;/span&gt;
        &lt;span class="c1"&gt;// for now, we could just pass it by reference&lt;/span&gt;
        &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;HttpRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="c1"&gt;// this is the buffer we will read into&lt;/span&gt;
            &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;streambuf&lt;/span&gt; &lt;span class="n"&gt;request_buffer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="c1"&gt;// this is the magic&lt;/span&gt;
            &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;read_until&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request_buffer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// why is this our delimiter? read on&lt;/span&gt;

            &lt;span class="c1"&gt;// this stream just makes it easier to extract strings from our request_buffer&lt;/span&gt;
            &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;istream&lt;/span&gt; &lt;span class="n"&gt;request_stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;request_buffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="c1"&gt;// why can we just do this? it's because the method, path, and version are deliniated by spaces in between, so we can reliably just extract them using the c++ std::istream&lt;/span&gt;
            &lt;span class="n"&gt;request_stream&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;response_handler&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// again, we'll get here later. make sure to add the include at the top of the file&lt;/span&gt;

            &lt;span class="c1"&gt;// we finally shutdown this socket&lt;/span&gt;
            &lt;span class="c1"&gt;// we don't have logic for reusing a socket, though it wouldn't be too difficult to add if you wanted to.&lt;/span&gt;
            &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;error_code&lt;/span&gt; &lt;span class="n"&gt;ignored_error&lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;
            &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;shutdown_both&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ignored_error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ignored_error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// existing code...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, all the code comments should explain what's going on.&lt;br&gt;
However, you may be interested that "\r\n" is our delimiter for reading the socket. That's because in HTTP, all new lines are separated by "\r\n" like CRLF line-endings on Windows.&lt;br&gt;
The method, path, and version are all on one line.&lt;br&gt;
Then, each header has its own line.&lt;br&gt;
Then, before the body, there is an extra blank line.&lt;br&gt;
Then, there is the body.&lt;/p&gt;

&lt;p&gt;So, if we wanted to read all the headers as well, we could just change the delimiter in read_until to be "\r\n\r\n",&lt;br&gt;
as the last header ends with "\r\n", then another "\r\n" after the last header for an extra blank line.&lt;br&gt;
All of this is guaranteed by the HTTP/1.1 spec.&lt;br&gt;
This is sufficient for our simplified parser, but production servers must handle partial reaads and malformed requests.&lt;/p&gt;
&lt;h4&gt;
  
  
  Layer 3: Router/Dispatcher
&lt;/h4&gt;

&lt;p&gt;If you were wondering what the &lt;code&gt;http::response_handler::dispatch(socket, request);&lt;/code&gt; was doing, here we are.&lt;br&gt;
Now that we have parsed the information we need out of the HTTP request, we can finally get to executing our custom logic based on each route.&lt;/p&gt;

&lt;p&gt;First, let's dispatch to those routes (routes are just paths).&lt;/p&gt;

&lt;p&gt;Add a new file:&lt;/p&gt;

&lt;p&gt;src/response_handler.h&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#pragma once
&lt;/span&gt;
&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;boost/asio.hpp&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// forward declaration. Would be cleaner to seperate out HttpRequest into a seperate file&lt;/span&gt;
    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;HttpRequest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// we don't need a whole class for this, so I just put it into a namespace&lt;/span&gt;
    &lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;response_handler&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quite a short file. The implementation file will be a little more lengthy, though.&lt;br&gt;
Let's get on to that.&lt;/p&gt;

&lt;p&gt;Add a new file:&lt;/p&gt;

&lt;p&gt;src/response_handler.cpp&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;"response_handler.h"&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;"tcp_server.h"&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;response_handler&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;path_handlers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Not Found"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Not Found"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;path_handlers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This may seem a little foreign, for good reason, considering I didn't put in any code comments.&lt;br&gt;
However, I hope you see the idea here.&lt;br&gt;
We have &lt;code&gt;path_handlers&lt;/code&gt;, essentially a jump table. It's an unordered_map with a key of std::string_view (path) and a function that does some logic.&lt;br&gt;
That will be part of layer 4: handler functions.&lt;br&gt;
We just execute the function that corresponds to the given path. If it doesn't exist, we respond with a 404 error.&lt;/p&gt;

&lt;p&gt;Speaking of 404, in HTTP there are certain status codes that have given meanings. 200 means OK. 404 means NOT FOUND. If you want to see more, see the MDN docs for HTTP.&lt;br&gt;
Status codes are only in HTTP responses, not requests.&lt;/p&gt;
&lt;h4&gt;
  
  
  Layer 4: Handler Functions
&lt;/h4&gt;

&lt;p&gt;We're finally at the last layer. Let's wrap this up with a nice little bow.&lt;/p&gt;

&lt;p&gt;Edit the file:&lt;/p&gt;

&lt;p&gt;src/response_handler.cpp&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// existing code&lt;/span&gt;

&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;unordered_map&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;map&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;string_view&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;chrono&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;format&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;fstream&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;literals&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="c1"&gt;// again, a C++ anonymous namespace&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// this gives a nice API to build and write HTTP Responses&lt;/span&gt;
        &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;HttpResponse&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;private:&lt;/span&gt;
            &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt; &lt;span class="c1"&gt;// i.e. HTTP/1.1&lt;/span&gt;
            &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt; &lt;span class="c1"&gt;// i.e. 404&lt;/span&gt;
            &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;status_line&lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt; &lt;span class="c1"&gt;// i.e. "NOT FOUND"&lt;/span&gt;
            &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;

            &lt;span class="c1"&gt;// some default headers we want&lt;/span&gt;
            &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"text/plain; charset=utf-8"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Access-Control-Allow-Origin"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"Connection"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"close"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;set_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;new_version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_version&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;set_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;new_status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;new_status_line&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="n"&gt;status_line&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_status_line&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;set_header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;set_body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;new_body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;move&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="c1"&gt;// Content-Lenght expects bytes&lt;/span&gt;
                &lt;span class="c1"&gt;// length == bytes for UTF-8&lt;/span&gt;
                &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"Content-Length"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sc"&gt;' '&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;to_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="sc"&gt;' '&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;status_line&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;": "&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
                &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

                &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boost&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;asio&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;


        &lt;span class="c1"&gt;// typedef for a function pointer, in our case we'll use lambdas. You could use any sort of function pointer, though&lt;/span&gt;
        &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="n"&gt;path_handler_fn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;unordered_map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string_view&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path_handler_fn&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;path_handlers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="c1"&gt;// the handler for the '/' path. The server will serve the whole html client html file&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[](&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="c1"&gt;// only the GET method is allowed at this path&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
                            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;405&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Method Not Allowed"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Method Not Allowed"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;


                    &lt;span class="c1"&gt;// binary mode is useful, and we start at the end of the file so that we can easily tell its length&lt;/span&gt;
                    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ifstream&lt;/span&gt; &lt;span class="nf"&gt;file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test_client/client.html"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ios&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;binary&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ios&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_open&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;good&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
                            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Internal Server Error"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to open client.html"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;

                    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tellg&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'\0'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;seekg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OK"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"text/html; charset=utf-8"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;

            &lt;span class="c1"&gt;// the handler for the '/time' path (if you remember, its for when the button is clicked)&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s"&gt;"/time"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[](&lt;/span&gt;&lt;span class="n"&gt;tcp&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

                    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;currentTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;chrono&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;system_clock&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
                    &lt;span class="c1"&gt;// nicely format the current time&lt;/span&gt;
                    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;timeString&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"{:%Y-%m-%d %H:%M:%S}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;currentTime&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;auto&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"OK"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set_body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// existing code&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wow, that was a doozy. But with that, we've added handler functions. We also added the API for building HttpResponses and writing them back to the client via the TCP socket.&lt;/p&gt;

&lt;p&gt;You've made the transition from a rookie understanding of HTTP to a solid, mid-level to senior-level understanding of HTTP.&lt;br&gt;
We started from raw Boost.Asio TCP sockets, and made it to serving an HTMX frontend.&lt;/p&gt;

&lt;p&gt;If you want to see your website, run the server and open &lt;code&gt;http://localhost:3000&lt;/code&gt; in your browser.&lt;/p&gt;

&lt;p&gt;Now, there are a few things left to implement. Those being concurrency and a templating engine.&lt;br&gt;
We also may have to handle CORS in the future. If you are encountering issues with CORS, see my up-to-date GitHub repo.&lt;br&gt;
The templating engine is really quite straightforward.&lt;br&gt;
Also, the Asio in Boost.Asio stands for "Async IO," so concurrency should be native to Asio.&lt;br&gt;
We'll find out soon.&lt;/p&gt;

&lt;p&gt;Read &lt;a href="https://www.amn.sh/blog/2025-12-15-http-server-in-cpp-part2" rel="noopener noreferrer"&gt;part 2&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes On the Build System
&lt;/h2&gt;

&lt;p&gt;Personally, I chose to use CMake for my build system.&lt;br&gt;
CMake is the de-facto standard for C++. Once you get familiar with CMake, it's not too bad.&lt;br&gt;
Build systems are the type of things you write once and copy paste into every new project you make (until it doesn't work).&lt;br&gt;
Regardless, to install Boost.Asio, I used &lt;code&gt;vcpkg&lt;/code&gt;, a C++ package manager made by Microsoft.&lt;br&gt;
In my experience, it's been the most reliable and easy to use C++ package manager.&lt;/p&gt;

&lt;p&gt;I would write out the build scripts here, but it's easier if you just look at the &lt;a href="https://github.com/ArmaanCPro/aychTTP/blob/main/CMakeLists.txt" rel="noopener noreferrer"&gt;repo&lt;/a&gt;.&lt;br&gt;
Look at the CMakeLists.txt file, the CMakePresets.json file, and the vcpkg.json file.&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>networking</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to Hone Windows for Development</title>
      <dc:creator>Armaan Chahal</dc:creator>
      <pubDate>Sat, 20 Sep 2025 00:16:00 +0000</pubDate>
      <link>https://forem.com/armaancpro/how-to-hone-windows-for-development-10oa</link>
      <guid>https://forem.com/armaancpro/how-to-hone-windows-for-development-10oa</guid>
      <description>&lt;h2&gt;
  
  
  Why Even Use Windows?
&lt;/h2&gt;

&lt;p&gt;In a lot of professional software development, you'll be using Windows.&lt;br&gt;
Fields like Game Development and Graphics Programming are the most prominent examples, but many SWE companies or teams just use Windows.&lt;br&gt;
I too enjoy using &lt;strong&gt;Linux&lt;/strong&gt;. I have Arch &amp;amp; Hyprland installed on my laptop, and Neovim is my preferred editor.&lt;/p&gt;

&lt;p&gt;However, my main workstation is a Windows 11 desktop computer I built myself. I know I'm talking extensively about myself, but I feel&lt;br&gt;
my own experience is fairly common among many of you. I do gaming on Windows, development on Windows, and most other tasks I do on Windows.&lt;/p&gt;
&lt;h3&gt;
  
  
  The Main Pain Points
&lt;/h3&gt;

&lt;p&gt;I hear a lot of people say "Just use WSL" especially for tools like Git, Node, etc. But, for our case, we won't be using WSL or anything other than native Windows 11.&lt;br&gt;
Yes, that includes MingW (a toolchain I used to use a lot).&lt;/p&gt;

&lt;p&gt;On the topic of Git, I don't use Git Bash or any other special git client.&lt;/p&gt;
&lt;h4&gt;
  
  
  Git
&lt;/h4&gt;

&lt;p&gt;I've simply just installed Git from the website and use it from Windows Terminal.&lt;br&gt;
In Windows Terminal, I use &lt;em&gt;PowerShell&lt;/em&gt; (the new version).&lt;br&gt;
Git works perfectly fine for me. It really is that simple.&lt;br&gt;
Actually, I'd recommend using a package manager like &lt;strong&gt;chocolatey&lt;/strong&gt; or &lt;strong&gt;winget&lt;/strong&gt; to install Git.&lt;/p&gt;
&lt;h4&gt;
  
  
  Package Managers
&lt;/h4&gt;

&lt;p&gt;I use both chocolatey and winget for package management. To be honest, winget is excellent. It has come a long way since I first checked it out.&lt;br&gt;
Both Winget and Chocolatey have a &lt;strong&gt;lot&lt;/strong&gt; of packages. However, I prefer chocolatey for one specific reason:&lt;br&gt;
It doesn't automatically configure itself with programs you installed using other installers.&lt;br&gt;
Winget will pick up installed programs on your machine regardless of how you installed them. This is a huge disadvantage for me.&lt;br&gt;
I don't want or need Winget to update Epic Games Launcher or Steam whenever I run &lt;code&gt;winget upgrade&lt;/code&gt;.&lt;br&gt;
Though, that &lt;em&gt;could&lt;/em&gt; be a benefit for you.&lt;/p&gt;

&lt;p&gt;There are also package managers like &lt;strong&gt;scoop&lt;/strong&gt; which I've heard good things about. I've never used it, though, so I can't speak to its specifics.&lt;br&gt;
It seems that scoop can install programs without Admin privileges, which may be good for people on work computers.&lt;/p&gt;
&lt;h3&gt;
  
  
  C/C++ Development
&lt;/h3&gt;

&lt;p&gt;C/C++ development is often something people mention as being &lt;strong&gt;terrible&lt;/strong&gt; on Windows.&lt;br&gt;
I'm happy to inform you that that isn't true.&lt;/p&gt;

&lt;p&gt;For any development workflow, make sure you install the latest version of Visual Studio.&lt;br&gt;
Not just for the IDE, but for all the tools it includes, like MSVC.&lt;br&gt;
You don't need to install CMake, Node, Python, etc. from it. I installed all of those separately.&lt;/p&gt;

&lt;p&gt;I use &lt;strong&gt;CMake&lt;/strong&gt; for the vast majority of my C/C++ projects.&lt;br&gt;
Normally, I use CLion, but I'm going to cover just Visual Studio for now (as most jobs that require Windows require Visual Studio).&lt;/p&gt;

&lt;p&gt;Visual Studio &lt;em&gt;can&lt;/em&gt; work well with CMake. But, don't be afraid to use Visual Studio .sln files if your entire team is using Visual Studio.&lt;/p&gt;

&lt;p&gt;With CMake, you don't even have to use the &lt;code&gt;Visual Studio 17 2022&lt;/code&gt; generator.&lt;br&gt;
You can use &lt;code&gt;Ninja&lt;/code&gt; as your generator, and just use MSVC (cl.exe) as the compiler.&lt;br&gt;
Make sure you add cl.exe to your PATH.&lt;br&gt;
In fact, the PATH is such an important part of your development environment that I recommend you add a lot of your tools to your PATH. Also understand &lt;em&gt;what&lt;/em&gt; the PATH &lt;em&gt;is&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;For compiling since C/C++ files, you can still use cl.exe. For some reason, the Visual Studio Code docs recommend using MingW for development.&lt;br&gt;
However, you can use cl.exe in your terminal for compiling single files.&lt;br&gt;
I usually do something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;cl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/EHsc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/std:c&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;latest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main.cpp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;/Fe:main.exe&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, if you can, you can also use MingW and gcc/clang for compiling single files.&lt;/p&gt;

&lt;h3&gt;
  
  
  MingW vs MSVC
&lt;/h3&gt;

&lt;p&gt;To preface, if you're using MingW, use either the Clang64 or UCRT64 toolchains, not the MINGW64 toolchain.&lt;/p&gt;

&lt;p&gt;The reason I don't use MingW anymore is that the compilation speed is incredibly slow. On my machine, the performance list goes like this:&lt;/p&gt;

&lt;p&gt;(fastest) MSVC with Ninja -&amp;gt; MSVC with .sln -&amp;gt; MingW with Ninja -&amp;gt; MingW with MingW Makefiles (slowest).&lt;/p&gt;

&lt;p&gt;MSVC, even with .sln, is around 40-50% faster than MingW in my own game engine project (moon engine).&lt;br&gt;
Now, as a compiler, is MSVC better than gcc or clang?&lt;br&gt;
It's comparable, but I do prefer gcc. I don't really use clang.&lt;br&gt;
But MSVC is still &lt;strong&gt;good&lt;/strong&gt;. It is not bad at all. My only slight annoyance is that it's errors and warnings are usually less strict than gcc/clang.&lt;br&gt;
So, when I use something like all warnings and warnings as errors, code that compiles with MSVC may fail with gcc/clang.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vim on Windows???
&lt;/h3&gt;

&lt;p&gt;Firstly, I use Neovim on Linux. The only time I &lt;strong&gt;ever&lt;/strong&gt; use Vim is when I'm SSH-ed on to a remote server that only has Vim installed.&lt;/p&gt;

&lt;p&gt;It's not feasible to use Neovim on Windows. Vim with plugins probably isn't reasonable either (haven't extensively tested though).&lt;br&gt;
Now, is it possible? Yes. But it doesn't work well. Many plugins are flat-out broken on Windows.&lt;br&gt;
Aside from the plugin issue, the Neovim workflow on Windows just isn't that good.&lt;br&gt;
Windows just isn't that good for terminal-based workflows. You can make it work, sure, but if you have &lt;em&gt;any&lt;/em&gt; Windows-only tooling,&lt;br&gt;
you're probably out of luck. For example, .sln files, just don't work with Neovim (no plugins I've found).&lt;/p&gt;

&lt;p&gt;However, as I mentioned earlier, I use CLion for C/C++ development.&lt;br&gt;
All Jetbrains IDEs have a plugin called &lt;code&gt;IdeaVim&lt;/code&gt; which works very well. It uses .vimrc, not lua like Neovim, but its functionality is exceptional.&lt;br&gt;
Check out my &lt;a href="https://gist.github.com/ArmaanCPro/59d559ba1587a510ae59603e212ff16c" rel="noopener noreferrer"&gt;IdeaVim .vimrc&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Even with Visual Studio, there are Vim emulator plugins like &lt;code&gt;VsVim&lt;/code&gt; that work decently well.&lt;br&gt;
For VS Code, there are Vim and Neovim extensions, but I think the Vim extension works the best.&lt;/p&gt;

&lt;p&gt;For me, I do have a heavily customized &lt;a href="https://github.com/ArmaanCPro/nvim-config" rel="noopener noreferrer"&gt;neovim config&lt;/a&gt;.&lt;br&gt;
However, .vimrc based vim emulators work well. For me, them most important thing is just basic vim motions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Other Programming Languages
&lt;/h3&gt;

&lt;p&gt;If you use package managers, chances are there is little you'll have to do aside from just &lt;code&gt;choco install &amp;lt;package&amp;gt;&lt;/code&gt;.&lt;br&gt;
Even something like rustup is installable through the terminal.&lt;/p&gt;

&lt;p&gt;The most common complaint of things just not working on Windows or requiring extensive customization &lt;em&gt;just isn't true&lt;/em&gt; for 99% of things these days.&lt;br&gt;
Just remember to have Visual Studio installed. It fixes a lot of problems with prereqs not being installed, or &lt;code&gt;redists&lt;/code&gt; not being installed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Don't fall down rabbit holes trying to make Windows just like Linux or some &lt;em&gt;perfect&lt;/em&gt; platform.&lt;br&gt;
Sure, you may have to find Windows-specific solutions, but they often work well.&lt;br&gt;
Nor does that prevent you from writing cross-platform software, or make you reliant on Windows.&lt;br&gt;
But remember that Windows is not perfect, but it is possible to do most things on it.&lt;/p&gt;

&lt;p&gt;A lot of niche Linux commands may not have direct equivalents on Windows, but you can probably install cli tools that achieve those results.&lt;br&gt;
i.e., fzf, fd, etc.&lt;br&gt;
Even if you can't, you can still use WSL. Of course, I tried to make everything in this article as Windows-only as possible, but sometimes you need those tools.&lt;/p&gt;

&lt;p&gt;Windows-specific tools usually work better than trying to force Linux tools into Windows, as shown with C/C++ development.&lt;/p&gt;

&lt;p&gt;I've been using both Windows and Linux for a long time. You can get very efficient with &lt;strong&gt;both&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>windows</category>
    </item>
    <item>
      <title>Harmony Between OOP and Data-Oriented Design</title>
      <dc:creator>Armaan Chahal</dc:creator>
      <pubDate>Thu, 04 Sep 2025 00:00:00 +0000</pubDate>
      <link>https://forem.com/armaancpro/harmony-between-oop-and-dod-2lj6</link>
      <guid>https://forem.com/armaancpro/harmony-between-oop-and-dod-2lj6</guid>
      <description>&lt;h2&gt;
  
  
  OOP For the Uninitiated
&lt;/h2&gt;

&lt;p&gt;Data-Oriented Design is something easy to understand but hard to &lt;em&gt;implement&lt;/em&gt;. There are no clear rules with DOD, nor any clear models to follow.&lt;br&gt;
Object-Oriented Programming follows the &lt;code&gt;model of the world&lt;/code&gt; approach. You think about how something works in the real world,&lt;br&gt;
and then you translate it into code. Take an example anyone can understand:&lt;br&gt;
    - You have a white chair&lt;br&gt;
    - You have a pink chair that is wider than the white one&lt;/p&gt;

&lt;p&gt;Clearly, both of these things have something in common. They are both chairs!&lt;br&gt;
This shared property is usually modeled with an abstract base class called &lt;code&gt;Chair&lt;/code&gt; with properties such as &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;color&lt;/code&gt;.&lt;br&gt;
These properties can be overridden by the derived classes, such as &lt;code&gt;PinkChair&lt;/code&gt; and &lt;code&gt;WhiteChair&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Chair&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="n"&gt;Chair&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;getWidth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;virtual&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string_view&lt;/span&gt; &lt;span class="n"&gt;getColor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PinkChair&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Chair&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;getWidth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;m_width&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string_view&lt;/span&gt; &lt;span class="n"&gt;getColor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;m_color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;m_width&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;m_color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"pink"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;WhiteChair&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Chair&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;public:&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;getWidth&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;getColor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"white"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inheritance is not a given of OOP, but it is a common pattern.&lt;/p&gt;

&lt;p&gt;Something that OOP does emphasize is having &lt;em&gt;invisible data&lt;/em&gt;.&lt;br&gt;
This means that you expose functions and hide the implementation details and state behind lock and key.&lt;br&gt;
The client only uses your public API and generally has no idea of the underlying implementation.&lt;br&gt;
Seems optimal, right?&lt;/p&gt;
&lt;h2&gt;
  
  
  DOD For the Uninitiated
&lt;/h2&gt;

&lt;p&gt;Data-Oriented Design takes a different approach, focusing on the data itself.&lt;br&gt;
When you model your code, you think about the data and the transformations of that data.&lt;br&gt;
This is a very abstract concept to grasp, especially when you are new to DOD.&lt;br&gt;
You may be thinking, "Okay, but what does that actually mean in code?"&lt;/p&gt;

&lt;p&gt;I had the same question. Let's revisit the &lt;code&gt;Chair&lt;/code&gt; example from above.&lt;br&gt;
How would you have multiple chairs? You would likely do something like &lt;code&gt;std::vector&amp;lt;Chair*&amp;gt;&lt;/code&gt;.&lt;br&gt;
This is widespread in OOP, and it is called an array of structures, or AOS.&lt;/p&gt;

&lt;p&gt;The alternate in DOD &lt;em&gt;could&lt;/em&gt; look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Chairs&lt;/span&gt; &lt;span class="k"&gt;final&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;widths&lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;{};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;import microBenchmarkSOAAOS from "./micro_benchmark_soa_aos.png";&lt;/p&gt;

&lt;p&gt;This is called a structure of arrays, or SOA.&lt;br&gt;
As an aside, if you do a micro-benchmark on this, you will likely see varying results.&lt;br&gt;
SOA won't be slower than AOS, but it will likely be very similar in terms of CPU cycles if you do something like this quick and dirty benchmark:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgf5jlk6rmv1opmfhx33x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgf5jlk6rmv1opmfhx33x.png" alt="SOA vs AOS Microbenchmark" width="800" height="460"&gt;&lt;/a&gt;&lt;br&gt;
In this micro-benchmark, SOA is a &lt;em&gt;little&lt;/em&gt; faster than AOS, but we aren't using polymorphism on the AOS (Chair*).&lt;br&gt;
Check out &lt;a href="https://youtu.be/i5MAXAxp_Tw?si=e-fTGH6gZjEhxTi" rel="noopener noreferrer"&gt;this talk&lt;/a&gt; for details about polymorphism and micro-benchmarks!&lt;/p&gt;
&lt;h3&gt;
  
  
  The Abstraction
&lt;/h3&gt;

&lt;p&gt;Abstraction is often times a point people new to DOD or traditional OOP programmers are confused with.&lt;br&gt;
Are you even supposed to abstract? How do you abstract? Ultimately, the question should be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What is the philosophy of abstraction?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer, as it always is with abstraction, is unclear. DOD purists will say that you should never abstract away the data,&lt;br&gt;
and that the client should always be aware of the data transformations. This results in very traditional, C89-style code. Consider this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Can you spot any problems?&lt;/p&gt;

&lt;p&gt;They are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The pointer to data is never deleted&lt;/li&gt;
&lt;li&gt;The range doesn't go through all the data (100000 vs 10000), though that &lt;em&gt;could&lt;/em&gt; be intended&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This may not seem like a big deal, but the problem scales as the code scales.&lt;/p&gt;

&lt;p&gt;There are four (five) horsemen of the apocalypse in low-level programming:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bounds Safety&lt;/li&gt;
&lt;li&gt;Type Safety&lt;/li&gt;
&lt;li&gt;Lifetime Safety&lt;/li&gt;
&lt;li&gt;Initialization Safety&lt;/li&gt;
&lt;li&gt;(Undefined Behavior, &lt;em&gt;sometimes&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The above example really doesn't account for any of these. At the very least, it doesn't use malloc, but you should never use &lt;code&gt;new&lt;/code&gt; in C++, so initialization safety has a big X.&lt;br&gt;
Obviously, bounds safety is not accounted for, we could copy-paste any bounds into the for loop. Lifetime safety is unaccounted for, we could forget to delete the pointer.&lt;br&gt;
Type safety may not seem like a problem here, but it could become one. What if you are convert your data array to be a different type, like a uint8_t?&lt;br&gt;
Sure, you may see that in this example, but what if you are getting data from a function that lives in a different file, where a different team works on it?&lt;/p&gt;

&lt;p&gt;So, a better example is this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;vector&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kt"&gt;size_t&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ranges&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;for_each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is much better and satisfies all the horsemen. However, this is not &lt;em&gt;pure&lt;/em&gt; DOD. The for_each is an abstraction,&lt;br&gt;
and though it is safer, it is hiding some of the code path/data transformation.&lt;br&gt;
Consider if we wanted to accumulate all the values. For that, we could use a for loop, which is pure DOD,&lt;br&gt;
but we could also use &lt;code&gt;std::reduce&lt;/code&gt; or &lt;code&gt;std::accumulate&lt;/code&gt; which, though safer, hides the code path and data transformation.&lt;br&gt;
However, this is far better code. Why?&lt;/p&gt;

&lt;h3&gt;
  
  
  The Harmony
&lt;/h3&gt;

&lt;p&gt;The number one advice I would give you for when you decide to abstract is to always be aware of the code flow and see if your&lt;br&gt;
abstractions are ever hiding important data transformations that the client would otherwise be unaware of.&lt;/p&gt;

&lt;p&gt;The next most important thing, and this could even be more important depending on what you're developing, is to be aware of the CPU.&lt;br&gt;
DOD is optimal because of the CPU cache. Check out &lt;a href="https://www.youtube.com/watch?v=WDIkqP4JbkE" rel="noopener noreferrer"&gt;this amazing talk&lt;/a&gt; by Scott Meyers for more details on the CPU cache.&lt;br&gt;
If you want a brief explanation, the CPU cache is a small amount of memory that lives very close to the CPU.&lt;br&gt;
It is the fastest memory to access, aside from registers, and is often used to store data that is accessed frequently.&lt;br&gt;
How does the cpu decide what to keep in the cache? It uses a heuristic called &lt;em&gt;locality of reference&lt;/em&gt; consisting of temporal locality and spatial locality.&lt;br&gt;
Temporal locality is a tendency of a program to access the same data repeatedly in a short time frame.&lt;br&gt;
Spatial locality is a program's tendency to access data nearby data already being accessed (think contiguous memory in an array).&lt;/p&gt;

&lt;p&gt;The CPU cache brings in data in a cache line, which is usually 64 bytes on most platforms. Whenever you are accessing data,&lt;br&gt;
know that you are using a cache line and don't waste the &lt;em&gt;limited&lt;/em&gt; data (If you're wondering what happens when you access data larger than a cache line, the CPU uses multiple lines).&lt;br&gt;
This is why SOA is so good, because it is &lt;em&gt;optimal&lt;/em&gt; for the cache line. If you only need the &lt;code&gt;colors&lt;/code&gt; of a &lt;code&gt;Chair&lt;/code&gt;, you don't need to waste the cache line with the &lt;code&gt;widths&lt;/code&gt;.&lt;br&gt;
Keep in mind that accessing memory is &lt;strong&gt;orders of magnitude&lt;/strong&gt; slower than doing something like division or square root.&lt;br&gt;
Optimize for the hardware, as Mike Acton would say in his &lt;a href="https://www.youtube.com/watch?v=rX0ItVEVjHc" rel="noopener noreferrer"&gt;great talk on DOD&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Going back to the &lt;strong&gt;harmony&lt;/strong&gt;, OOP is not mutually exclusive with DOD.&lt;br&gt;
You can, and &lt;em&gt;should&lt;/em&gt;, use both. DOD does not mean using only SOA, it means that in performance-critical code paths, you&lt;br&gt;
code while being aware of the hardware. Ultimately, your code is always executing on hardware, and you have to be aware of what is happening.&lt;br&gt;
That is the only way to write good, performant code.&lt;/p&gt;

&lt;p&gt;Using traditional design patterns is not forbidden, and some of them are still useful. Sure, a &lt;code&gt;std::variant&lt;/code&gt; isn't the most optimal way to have polymorphic data,&lt;br&gt;
but it is still useful and a good abstraction. It may be &lt;em&gt;just as good&lt;/em&gt; as a more DOD struct of function pointers that are initialized at runtime or compile time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;DOD is not a silver bullet. But it is a mindset that everyone should have. Even in the world of web development,&lt;br&gt;
having fast websites is still important. Performance should be a top priority of everyone.&lt;br&gt;
Back in the day, people would code specifically knowing basically what every line of code was doing, and how many CPU cycles it was taking.&lt;br&gt;
Nowadays, we use tools with higher level abstractions. This isn't wrong. This is a good step. Otherwise, all performance-critical code would still be written in assembly.&lt;br&gt;
Of course, that isn't the case. A core philosophy of C++ is &lt;code&gt;Zero-Overhead Abstractions&lt;/code&gt;. Rust has &lt;code&gt;Zero-Cost Abstractions&lt;/code&gt;, which means the same thing in essence. Use abstractions when they are more declarative, have clear data transformations (i.e., &lt;code&gt;accumulate&lt;/code&gt; should clearly just loop through a range and add up the values).&lt;/p&gt;

&lt;p&gt;On the topic of encapsulation, it is still necessary to encapsulate your data for the sake of separation of data, though encapsulation in DOD is different from OOP. You're not encapsulating &lt;em&gt;or&lt;/em&gt; abstracting for the sake of hiding data, you're doing it for the sake of being able to scale up your &lt;em&gt;data&lt;/em&gt; as your &lt;em&gt;application scales&lt;/em&gt; up.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://youtu.be/i5MAXAxp_Tw?si=e-fTGH6gZjEhxTi" rel="noopener noreferrer"&gt;Optimizing Away C++ Virtual Functions May Be Pointless&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=WDIkqP4JbkE" rel="noopener noreferrer"&gt;Scott Meyers: Cpu Caches and Why You Care&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=rX0ItVEVjHc" rel="noopener noreferrer"&gt;Mike Acton "Data-Oriented Design and C++"&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtu.be/yy8jQgmhbAU?si=LM3nsyep4OXNyE_w" rel="noopener noreferrer"&gt;OOP Is Dead, Long Live Data-Oriented Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtu.be/IroPQ150F6c?si=rOhBII0-L7sRg9hX" rel="noopener noreferrer"&gt;Andrew Kelley Practical Data Oriented Design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://curtclifton.net/papers/MoseleyMarks06a.pdf" rel="noopener noreferrer"&gt;Out of the Tar Pit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cpp</category>
      <category>learning</category>
      <category>architecture</category>
      <category>softwareengineering</category>
    </item>
  </channel>
</rss>
