Your next product probably needs an HTTP server, and it probably does not need nginx. When the web server lives inside your firmware, your desktop tool, your router admin panel, or your test harness, the right move is an embeddable HTTP library: a C library that links into your process, opens a port, and exposes your functions as routes. The three serious contenders in 2026 are Mongoose (13,025 GitHub stars), CivetWeb (3,447 stars), and GNU libmicrohttpd — and they differ far more than their similar APIs suggest.
Choose wrong and you discover it late: the GPL license that kills your commercial SDK, the threading model that fights your event loop, or the TLS stack you cannot swap. This guide compares the three with real code from the official repositories so you can decide in one sitting.
TL;DR — Which Embedded HTTP Library Should You Pick?
Pick Mongoose if you target microcontrollers or need a tiny single-file server with a built-in network stack — it is the only one of the three that runs on bare-metal MCUs, but its dual GPLv2/commercial license matters if you sell closed-source products. Pick CivetWeb if you want a permissively licensed (MIT core), multi-threaded, handler-based server with batteries included — CGI, TLS, WebSockets, and a C++ wrapper out of the box. Pick GNU libmicrohttpd if you need the cleanest LGPL story for a proprietary application and prefer to own the I/O loop yourself.
Mongoose vs CivetWeb vs libmicrohttpd: The 2026 Comparison
| Dimension | Mongoose | CivetWeb | GNU libmicrohttpd |
|---|---|---|---|
| GitHub stars | 13,025 | 3,447 | n/a (GNU project; ~151-star maintainer mirror) |
| Last push (2026) | Sep 3 | Aug 1 | Apr 16 (mirror) |
| License | Dual GPLv2 / commercial | MIT (core) | LGPL-2.1-or-later (+ eCos dual clause) |
| Distribution | Single-file mongoose.c + mongoose.h | Multi-file C/C++ source tree | Multi-file C source tree |
| Threading model | Single-threaded event loop (mg_mgr_poll) | Multi-threaded (thread per connection) | Your choice: external poll, internal threads, thread-per-connection |
| TLS | mbedTLS, OpenSSL, or built-in for MCUs | OpenSSL, wolfSSL, mbedTLS | GnuTLS |
| WebSocket server | Yes | Yes | Yes (websocket.c example) |
| MCU / RTOS support | Excellent (ESP32, STM32, …) | Limited (desktop/server oriented) | No (POSIX/Windows) |
| Static file serving | Yes | Yes (document_root) | Manual (no built-in static file handler) |
| C++ API | No | Yes (CivetServer class) | No |
| Built-in auth | Yes (digest/basic) | Yes | Yes (basic/digest) |
| Documentation | mongoose.ws | civetweb.com + reference manual | GNU manual (tutorial + API reference) |
Decision matrix — 10-second pick
| Use case | Recommendation | Why |
|---|---|---|
| ESP32 / STM32 firmware with a config UI | Mongoose | Runs on bare metal; built-in TCP/IP stack for MCUs |
| Closed-source commercial app | CivetWeb or libmicrohttpd | MIT and LGPL are safe for proprietary linking; Mongoose GPLv2 is not |
| Router/desktop app with static pages + REST | CivetWeb | document_root + request handlers cover 90% of needs |
| Library that must not dictate your event loop | libmicrohttpd | You keep select()/epoll() ownership; MHD just parses and replies |
| Max-license-purity for an open-source product | Mongoose (GPL) | If you are GPL anyway, Mongoose’s GPL side costs nothing |
| WebSocket + REST on a Linux daemon | CivetWeb | One library, both protocols, no external event loop required |
Mongoose — The Single-File Server That Runs on a Microcontroller
Mongoose is the oldest name here and the most unusual: the whole server is two files (mongoose.c and mongoose.h) that you drop into any project — from a 40 MHz MCU to a Linux service. Its site describes it as an “embedded web server and web UI framework for microcontrollers,” and it genuinely runs on bare metal, where it can even bring its own TCP/IP stack when the silicon has none.
The programming model is a single-threaded event loop. The official README example starts a server with a REST endpoint that returns the current time:
| |
The surrounding main() shows the whole lifecycle — initialize an event manager, attach a listener, and poll forever:
| |
Strengths: absurd portability, tiny footprint (tens of KB), WebSocket/MQTT/HTTP client and server in one amalgamation, and an event-driven design that needs no threads and no locks. Cesanta pushes updates almost daily (last push September 3, 2026).
Costs: the dual GPLv2/commercial license — the LICENSE file states the code is “dual-licensed” under GPLv2, and commercial use of Mongoose in proprietary products requires a paid Cesanta license. Also, the event-loop style inverts how many C developers think about servers: every blocking call in a handler stalls the whole server, so file I/O and crypto must be used carefully.
CivetWeb — The Permissively Licensed Multi-Threaded Workhorse
CivetWeb began life as a fork of an early Mongoose release and has since grown into its own mature project: a multi-threaded C/C++ web server that embeds in a few lines. Where Mongoose hands you an event loop, CivetWeb hands you threads — each connection is handled concurrently, so your handlers can block on file or database I/O without stalling other clients.
The official embedded_c example shows the startup pattern:
| |
options is a NULL-terminated array of key/value strings — the example configures a document root and listening ports with a compact syntax where r/s suffixes toggle HTTP vs HTTPS per port: "8888r,8843s,8884" serves HTTP on 8888, HTTPS on 8843, and plain HTTP on 8884 simultaneously. One process, many protocols, no virtual-host gymnastics.
Beyond the C API, CivetWeb ships CivetServer, a C++ wrapper class, plus optional Lua server pages, CGI support, digest authentication, WebSocket handlers, and an SSL layer that works with OpenSSL, wolfSSL, or mbedTLS. The project is quiet-but-alive — last push August 1, 2026 — and its stability is the feature: the API has barely churned in a decade.
Strengths: permissive licensing (the example sources state the MIT License), concurrency for free, static files + handlers + TLS in one API, huge feature surface.
Costs: heavier than Mongoose (multi-file build, more RAM per connection), less at home on bare-metal MCUs, and the thread-per-connection model is a poor fit for event-driven architectures with tens of thousands of connections.
GNU libmicrohttpd — The Library That Stays Out of Your Way
GNU libmicrohttpd (MHD) takes the most conservative design position: it is a C library that implements HTTP 1.1 parsing and responses, period. It does not want your main loop, does not serve static files for you, and does not decide your threading strategy — you pass it a callback and choose one of several run modes (external event polling, internal thread per connection, or a fixed thread pool). That makes it the favorite of projects like GNUnet that need an HTTP server integrated into an existing event architecture.
The canonical “hello browser” example from the official sources is delightfully small:
| |
Every request funnels through your callback; you decide what to do with the URL, method, and headers. MHD handles the protocol minutiae — keep-alive, chunked transfer encoding, digest auth, TLS via GnuTLS, and even the HTTP Upgrade flow for WebSockets (see the websocket.c example) — while you keep ownership of the application.
Strengths: the friendliest license of the trio for proprietary software (LGPL-2.1-or-later, with a dual-license clause for non-SSL builds per the COPYING file), superb protocol correctness, a documented GNU coding environment, and no opinion about your I/O architecture.
Costs: no built-in static file serving or routing — you write those. The callback API is more verbose than CivetWeb’s handler registration, and the project is conservative by design: features arrive slowly, which is precisely why it has been stable since 2001.
Licensing, Threading & Other Traps
- License mismatch is the expensive mistake. Mongoose is GPLv2/commercial dual-licensed: if your product is proprietary and you do not buy a license, you cannot ship it. CivetWeb (MIT core) and libmicrohttpd (LGPL) both permit proprietary use — LGPL additionally requires that you allow users to replace the library (relink), which dynamic linking or provided object files satisfy in practice.
- Threading model is a feature, not an implementation detail. Mongoose’s single-threaded event loop demands non-blocking handlers; CivetWeb’s threads let you write blocking handlers but cost RAM per connection; libmicrohttpd lets you pick per deployment. Match the model to your other I/O, not to the HTTP code.
- TLS stack lock-in. Mongoose and CivetWeb let you choose mbedTLS/OpenSSL/wolfSSL; libmicrohttpd is GnuTLS. If your org standardizes on one crypto provider, verify support before committing — swapping later means re-testing every handshake path.
- Static files are not free. CivetWeb serves a directory with one option (
document_root); Mongoose needs a handler for static assets or its built-in file serving enabled; libmicrohttpd gives you nothing — you stream files yourself, including range requests if you want video seeking to work. - The name “Mongoose” is overloaded. The C library (cesanta/mongoose) shares its name with a JavaScript ODM for MongoDB and a bicycle brand. When searching for docs or filing bugs, always qualify: “Cesanta Mongoose” or “mongoose.ws”.
- Port reuse and graceful restart. CivetWeb and MHD both support SO_REUSEPORT-style setups, but CivetWeb’s multi-threaded accepts can misbehave under aggressive restart loops if lingering connections hold the port. Test your supervisor’s restart policy early.
- If you are comparing full web servers instead of libraries, see our nginx vs Caddy vs OpenResty guide — and for the JVM equivalent of this decision, our Jetty vs Netty vs Undertow vs Tomcat comparison covers embedded HTTP in Java. For WebSocket-specific libraries in C++, our websocketpp vs Beast vs IXWebSocket guide fills the gap when you need sockets beyond HTTP.
FAQ
What is an embedded HTTP server library? A C library that you link into your own program so it can serve HTTP requests without a separate web server process. Examples include Mongoose, CivetWeb, and GNU libmicrohttpd — all three are used inside firmware, desktop applications, and appliances to expose configuration UIs and REST APIs.
Can I use Mongoose in a commercial closed-source product? Only with a commercial license from Cesanta. The library is dual-licensed under GPLv2 and a paid commercial license — the LICENSE file states this explicitly. CivetWeb (MIT core) and libmicrohttpd (LGPL) are the usual choices for proprietary products without a licensing budget.
Which library is best for the ESP32? Mongoose is the standard answer: it is designed for microcontrollers, can use its own lightweight TCP/IP stack, and its single-file amalgamation compiles in ESP-IDF and Arduino projects. CivetWeb targets desktop/server-class systems and libmicrohttpd requires a POSIX or Windows environment.
Does libmicrohttpd support WebSockets?
Yes — the official sources include a websocket.c example. MHD handles the HTTP Upgrade handshake; you then drive the socket through your own event loop. It is more plumbing than CivetWeb’s WebSocket handler, but it fits MHD’s philosophy of leaving I/O ownership to you.
How do these compare to running nginx inside a container? Embedded libraries win when the HTTP surface is small, the deployment is a single binary, or the host is a microcontroller; nginx wins on concurrency, static-file performance, and battle-tested TLS termination at scale. Many products do both: an embedded server for local config and a reverse proxy for public traffic.
Is CivetWeb still maintained in 2026? Yes — the repository received its latest push on August 1, 2026, and the project’s decade-long API stability is deliberate. Development is slower than Mongoose’s near-daily commits, but the project remains the most feature-complete permissively licensed option.
💰 想测试你的市场判断力?我用 Polymarket 做预测市场交易——这是全球最大的预测市场平台,从大选结果到技术监管时间线,什么都可以押注。和赌博不同,这是真正的信息市场:你懂的信息越多,胜率越高。我靠预测技术相关事件的走向已经赚了不少。用我的邀请链接注册:Polymarket.com