Project 16: C++20 Coroutine HTTP Server
An HTTP server using C++20 coroutines where handlers are written with
co_await—looking like synchronous code but running asynchronously. Build on top of your epoll/io_uring code.
Quick Reference
| Attribute | Value |
|---|---|
| Primary Language | C++20 |
| Alternative Languages | Rust (async/await), Go (goroutines) |
| Difficulty | Level 4: Expert |
| Time Estimate | 3 weeks |
| Knowledge Area | C++20 Coroutines, Executors, Async Patterns |
| Tooling | Modern async server framework |
| Prerequisites | Projects 9 or 15, solid C++17 knowledge |
What You Will Build
An HTTP server using C++20 coroutines where handlers are written with co_await—looking like synchronous code but running asynchronously. Build on top of your epoll/io_uring code.
Why It Matters
This project builds core skills that appear repeatedly in real-world systems and tooling.
Core Challenges
- Understanding coroutine mechanics → maps to promise_type, coroutine_handle
- Building awaitable types → maps to await_ready, await_suspend, await_resume
- Integrating with event loop → maps to resuming coroutines on I/O completion
- Error propagation → maps to exceptions in coroutines
Key Concepts
- C++20 Coroutines: “C++20 - The Complete Guide” Chapters 14-16 - Josuttis
- Awaitable Types: “C++ Concurrency in Action, 2nd Ed” Chapter 13 - Williams
- Coroutine Theory: Lewis Baker’s blog posts (essential reading)
- Integration Patterns: Asio with coroutines
Real-World Outcome
// Handler code looks synchronous but runs async!
Task<HttpResponse> handle_request(HttpRequest req) {
std::string body = co_await read_file_async(req.path);
co_return HttpResponse{200, "OK", body};
}
Task<void> handle_connection(TcpStream stream) {
while (true) {
HttpRequest req = co_await stream.read_request();
HttpResponse resp = co_await handle_request(req);
co_await stream.write_response(resp);
}
}
Implementation Guide
- Reproduce the simplest happy-path scenario.
- Build the smallest working version of the core feature.
- Add input validation and error handling.
- Add instrumentation/logging to confirm behavior.
- Refactor into clean modules with tests.
Milestones
- Milestone 1: Minimal working program that runs end-to-end.
- Milestone 2: Correct outputs for typical inputs.
- Milestone 3: Robust handling of edge cases.
- Milestone 4: Clean structure and documented usage.
Validation Checklist
- Output matches the real-world outcome example
- Handles invalid inputs safely
- Provides clear errors and exit codes
- Repeatable results across runs
References
- Main guide:
LEARN_CPP_NETWORK_PROGRAMMING.md - “C++20 - The Complete Guide” by Nicolai Josuttis