GNU libmicrohttpd (MHD) is a small C library that lets an application act as an HTTP 1.1 server without forking a separate process or thread pool unless you ask it to. Its design emphasises minimal footprint, straightforward API, and license compatibility (LGPL‑2.1+) making it suitable for embedded devices, CLI utilities, desktop apps, or even high‑performance back‑ends. Key features include:
select()
/poll()
/epoll()
, MHD_USE_THREAD_PER_CONNECTION, or thread‑pool models.iovec
responses since 0.9.73.Note: As of April 2025 Ubuntu ships MHD 1.0.1, the first “1.x” release focusing on long‑term ABI stability.
MHD exposes opaque pointers so your program never touches internal state directly:
MHD adopts an event‑driven design. Your application registers function pointers that the library invokes when:
#include <microhttpd.h> #include <string.h> #define PORT 8080 static int answer (void *cls, struct MHD_Connection *c, const char *url, const char *method, const char *ver, const char *u, size_t *s, void **con_cls) { static const char page[] = "Hello World\n"; struct MHD_Response *r = MHD_create_response_from_buffer (strlen (page), (void *) page, MHD_RESPMEM_PERSISTENT); int ret = MHD_queue_response (c, MHD_HTTP_OK, r); MHD_destroy_response (r); return ret; } int main () { struct MHD_Daemon *d = MHD_start_daemon ( MHD_USE_SELECT_INTERNALLY, PORT, NULL, NULL, // accept-policy cb &answer, NULL, // request handler cb MHD_OPTION_END); getchar (); // wait for ⏎ MHD_stop_daemon (d); return 0; }
Compile: gcc hello.c -lmicrohttpd -o hello
Run: ./hello
and visit http://localhost:8080
.
MHD_YES
, MHD calls your
MHD_ContentReaderCallback (or POST processor) chunk‑by‑chunk.Function | Typical Use‑Case |
---|---|
MHD_create_response_from_buffer | Small static strings held in memory. |
MHD_create_response_from_fd | Efficient sendfile() of large files. |
MHD_create_response_from_callback | Generate/stream data on demand (e.g., DB rows). |
MHD_create_response_from_iovec | Zero‑copy scatter‑gather, new since 0.9.73. |
After constructing you attach it with MHD_queue_response(). Custom headers are applied using MHD_add_response_header().
For application/x-www-form-urlencoded
and
multipart/form-data
bodies call
MHD_create_post_processor() inside your access‑handler,
then feed chunks to MHD_post_process().
This keeps memory usage O(chunkSize) instead of O(bodySize).
Compile MHD against your preferred SSL backend (--with-ssl=gnutls
|openssl
|mbedtls
).
At runtime pass one of:
MHD_start_daemon (MHD_USE_THREAD_PER_CONNECTION | MHD_USE_TLS, /* ← enable SSL */ 443, NULL, NULL, &handler, NULL, MHD_OPTION_HTTPS_MEM_KEY, key_pem, MHD_OPTION_HTTPS_MEM_CERT, cert_pem, MHD_OPTION_END);
The library automatically performs the TLS handshake before invoking your access callback.
Example file‑server with TLS is shipped in https_fileserver_example.c
.
select()
.SO_REUSEPORT
on Linux 3.9+ to allow multi‑daemon scaling.sendfile()
or iovec responses for static assets.Host
header if generating absolute redirects.git clone https://git.gnunet.org/libmicrohttpd.git cd libmicrohttpd ./bootstrap ./configure --prefix=/usr/local --enable-messages --with-ssl=openssl make -j$(nproc) sudo make install
Add pkg-config --cflags --libs libmicrohttpd
to your build system.
If you rely on CMake, use find_package(PkgConfig) …
.
Library | Notes |
---|---|
libevent‑httpd | Part of libevent; larger code base, no built‑in TLS. |
civetweb / mongoose | Header‑only single‑file; BSD/MIT licensed; no LGPL obligations. |
Boost.Beast | Modern C++; header‑only, but heavier compile times. |