libmicrohttpd clib Networking / HTTP

GNU embedded HTTP server. REST API endpoints, Basic auth, TLS, thread pool, POST forms, file serving. Single-file HTTP server in minutes.

ppm install libmicrohttpd

Overview

libmicrohttpd wraps GNU libmicrohttpd — a small C library that lets you embed a full HTTP/1.1 server inside any program. No separate server process required; the listener runs in your PascalAI application alongside your agents and business logic.

It handles the full HTTP protocol: persistent connections, chunked transfer encoding, pipelining, TLS via GnuTLS, and POST body parsing for both form-urlencoded and multipart data. Three threading models cover everything from single-threaded embedded devices to high-concurrency API servers.

CLib package

Requires libmicrohttpd-dev on the host system. Ubuntu/Debian: sudo apt install libmicrohttpd-dev

Key Features

FeatureDetails
HTTP/1.1Persistent connections, chunked transfer encoding, request pipelining
TLSHTTPS via GnuTLS; pass PEM cert and key file paths to StartTLS
Thread modesInternal select loop, one thread per connection, or fixed thread pool
POST / formsIncremental POST body processing; form-urlencoded and multipart file uploads
AuthHTTP Basic authentication with realm challenge; Digest auth via underlying lib
Suspend / resumePause a connection mid-handler for async back-end calls, then resume it
Static filesServe files directly from disk with NewFileResponse; uses sendfile(2)
IPv4 + IPv6Dual-stack support out of the box on all platforms

Thread Modes

ModeValueUse case
mmSelectInternally0Single background thread runs the select loop. Good for low-traffic services or when you want minimal resource use.
mmThreadPerConn1Spawns one thread per accepted connection. Simple handler code with no non-blocking constraints. Works well for long-lived connections.
mmThreadPool2Fixed pool of N worker threads shared across all connections. Best throughput for many short requests. Use StartPool(Port, N).

Comparison

LibraryNotes
vs nginxMHD is embeddable inside your process; nginx is a standalone reverse proxy/server. Choose MHD when you want one binary with no external dependencies.
vs MongooseSimilar scope and philosophy. MHD is GNU-licensed with stronger portability guarantees and a more conservative, stable C API.
vs cpp-httplibcpp-httplib is C++ only and header-only. MHD is pure C with a stable ABI — easier to bind from Pascal.

Quick Start

Minimal REST API server (GET /hello, POST /echo)

uses libmicrohttpd;

var d := Start(8080, mmThreadPerConn);
WriteLn('Listening on http://localhost:8080');

var req: TMHDRequest;
var conn: TMHDConn;

while WaitRequest(d, 5000, req, conn) do
begin
  if (req.Method = 'GET') and (req.Path = '/hello') then
    SendJSON(conn, 200, '{"message":"Hello, world!"}')

  else if (req.Method = 'POST') and (req.Path = '/echo') then
    SendJSON(conn, 200, req.Body)   { echo the raw body back }

  else
    NotFound(conn);
end;

Stop(d);

JSON API with Basic auth and thread pool

uses libmicrohttpd;

const
  API_USER = 'admin';
  API_PASS = 's3cr3t';

var d := StartPool(8443, 4);   { 4-thread pool on port 8443 }
WriteLn('API server on :8443 (4 threads)');

var req: TMHDRequest;
var conn: TMHDConn;

while WaitRequest(d, -1, req, conn) do
begin
  { Guard all routes with Basic auth }
  if not CheckBasicAuth(conn, API_USER, API_PASS) then
  begin
    ChallengeBasicAuth(conn, 'My API');
    continue;
  end;

  if req.Path = '/api/status' then
  begin
    var active := ActiveConnections(d);
    SendJSON(conn, 200,
      '{"status":"ok","connections":' + IntToStr(active) + '}');
  end

  else if req.Path = '/api/files' then
  begin
    var resp := NewFileResponse('/var/www/index.html');
    SetContentType(resp, 'text/html; charset=utf-8');
    SendResponse(conn, 200, resp);
  end

  else
    NotFound(conn);
end;

Stop(d);

Types

TypeUnderlyingDescription
TMHDDaemonIntegerRunning HTTP server handle returned by Start / StartTLS / StartPool
TMHDConnIntegerPer-request connection handle; passed to all response and auth functions
TMHDRespIntegerResponse object built by NewResponse, NewFileResponse, or NewStreamResponse
TMHDPostProcIntegerPOST body processor for form-urlencoded and multipart data
TMHDModeenumThreading model: mmSelectInternally, mmThreadPerConn, mmThreadPool
TMHDRequestrecordPopulated by PollRequest / WaitRequest; contains Method, URL, Path, Query, Version, RemoteIP, Headers, Body, ContentLen
TMHDStatusenumNamed HTTP status codes (200 msOK … 503 msServiceUnavailable) for use as integer literals

Server Lifecycle

FunctionDescription
Start(Port, Mode)Start an HTTP server on the given port using the specified threading mode. Returns a daemon handle.
StartTLS(Port, Mode, CertPEM, KeyPEM)Start with HTTPS. CertPEM and KeyPEM are paths to PEM files on disk.
StartPool(Port, Threads)Convenience: start with mmThreadPool and a fixed number of worker threads.
Stop(D)Gracefully shut down the server and free all associated resources.
RunLoop(D, TimeoutMs)Drive the select loop manually from your own event loop (only needed with mmSelectInternally).

Request Handling

FunctionDescription
PollRequest(D, out Req, out Conn)Non-blocking poll for the next request. Returns True if a request is ready; False if the queue is empty.
WaitRequest(D, TimeoutMs, out Req, out Conn)Block until a request arrives or the timeout (ms) elapses. Pass -1 to wait indefinitely.
GetHeader(Conn, Name)Return the value of a specific request header by name, or empty string if absent.
GetQueryParam(Conn, Name)Return the value of a URL query parameter (e.g. ?id=42GetQueryParam(conn, 'id') = '42').

Response Building

Build a response object, optionally attach headers, then send it with SendResponse. The library destroys the response after sending.

FunctionDescription
NewResponse(Body)Create a response with a string body (held in memory).
NewFileResponse(Path)Create a response backed by a file on disk. Uses sendfile(2) for zero-copy transfer. Supports range requests automatically.
NewStreamResponseCreate a chunked streaming response; write chunks to it incrementally.
AddHeader(Resp, Name, Value)Attach an arbitrary HTTP response header.
SetContentType(Resp, ContentType)Shortcut to set the Content-Type header.
SendResponse(Conn, Status, Resp)Send the response with the given HTTP status code and destroy the response object.

Convenience Helpers

One-liner helpers that create, configure, and send a response in a single call.

FunctionDescription
SendJSON(Conn, Status, JSON)Send a JSON string. Sets Content-Type: application/json automatically.
SendText(Conn, Status, Text)Send plain text. Sets Content-Type: text/plain.
SendHTML(Conn, Status, HTML)Send an HTML string. Sets Content-Type: text/html.
Redirect(Conn, URL, Permanent)Send a 301 (permanent) or 302 (temporary) redirect to URL.
NotFound(Conn)Send a 404 Not Found response with an empty body.

POST Body

Use the POST processor API for form submissions and file uploads. Feed body data incrementally as it arrives, then extract named fields.

FunctionDescription
NewPostProc(Conn)Create a POST body processor for this connection. Handles both application/x-www-form-urlencoded and multipart/form-data.
PostProcFeed(PP, Data)Feed a chunk of the raw POST body into the processor. Call repeatedly as data arrives.
GetPostField(PP, Name)Retrieve the value of a named form field after all chunks have been fed.
FreePostProc(PP)Release the POST processor and its internal buffers.
uses libmicrohttpd;

{ Handle a form POST to /submit }
var req: TMHDRequest;
var conn: TMHDConn;
var d := Start(8080, mmSelectInternally);

while WaitRequest(d, -1, req, conn) do
begin
  if (req.Method = 'POST') and (req.Path = '/submit') then
  begin
    var pp := NewPostProc(conn);
    PostProcFeed(pp, req.Body);
    var name  := GetPostField(pp, 'name');
    var email := GetPostField(pp, 'email');
    FreePostProc(pp);
    SendJSON(conn, 200, '{"ok":true,"name":"' + name + '"}');
  end
  else
    NotFound(conn);
end;

Stop(d);

Authentication

FunctionDescription
CheckBasicAuth(Conn, Username, Password)Verify the HTTP Basic credentials in the request Authorization header. Returns True if they match.
ChallengeBasicAuth(Conn, Realm)Send a 401 Unauthorized response with a WWW-Authenticate: Basic realm="..." challenge header.

Info

FunctionDescription
ActiveConnections(D)Returns the current number of open connections on the daemon.
MHDVersionReturns the version string of the underlying libmicrohttpd C library (e.g. '0.9.77').
Tip — thread safety

WaitRequest / PollRequest are the only daemon-level calls you make from your main loop. Once you have a TMHDConn handle, all response functions for that connection are safe to call from any thread — useful with mmThreadPool.

Package Info

Version1.0.0
Typeclib
C Librarylibmicrohttpd-dev
Authorgustavo

System Requirements

libmicrohttpd-dev

Ubuntu/Debian:
sudo apt install libmicrohttpd-dev

TMHDStatus Codes

msOK — 200
msCreated — 201
msNoContent — 204
msBadRequest — 400
msUnauthorized — 401
msForbidden — 403
msNotFound — 404
msMethodNotAllowed — 405
msConflict — 409
msUnprocessableEntity — 422
msTooManyRequests — 429
msInternalError — 500
msNotImplemented — 501
msServiceUnavailable — 503

Functions

  • Start / StartTLS / StartPool
  • Stop / RunLoop
  • PollRequest / WaitRequest
  • GetHeader / GetQueryParam
  • NewResponse / NewFileResponse
  • NewStreamResponse
  • AddHeader / SetContentType
  • SendResponse
  • SendJSON / SendText / SendHTML
  • Redirect / NotFound
  • NewPostProc / PostProcFeed
  • GetPostField / FreePostProc
  • CheckBasicAuth
  • ChallengeBasicAuth
  • ActiveConnections
  • MHDVersion

See Also