title: "Static File Server"
cpp-httplib can serve static files too — HTML, CSS, images, you name it. No complicated configuration required. One call to set_mount_point() is all it takes.
Let's jump right in. set_mount_point() maps a URL path to a local directory.
#include "httplib.h"
#include <iostream>
int main() {
httplib::Server svr;
svr.set_mount_point("/", "./html");
std::cout << "Listening on port 8080..." << std::endl;
svr.listen("0.0.0.0", 8080);
}
The first argument is the URL mount point. The second is the local directory path. In this example, requests to / are served from the ./html directory.
Let's try it out. First, create an html directory and add an index.html file.
mkdir html
<!DOCTYPE html>
<html>
<head><title>My Page</title></head>
<body>
<h1>Hello from cpp-httplib!</h1>
<p>This is a static file.</p>
</body>
</html>
Compile and start the server.
g++ -std=c++17 -o server server.cpp -pthread
./server
Open http://localhost:8080 in your browser. You should see the contents of html/index.html. Visiting http://localhost:8080/index.html returns the same page.
You can also access it with the client code from the previous chapter, or with curl.
httplib::Client cli("http://localhost:8080");
auto res = cli.Get("/");
if (res) {
std::cout << res->body << std::endl; // HTML is displayed
}
curl http://localhost:8080
You can call set_mount_point() as many times as you like. Each URL path gets its own directory.
svr.set_mount_point("/", "./public");
svr.set_mount_point("/assets", "./static/assets");
svr.set_mount_point("/docs", "./documentation");
A request to /assets/style.css serves ./static/assets/style.css. A request to /docs/guide.html serves ./documentation/guide.html.
Static file serving and routing handlers — the kind you learned about in the previous chapter — work side by side.
httplib::Server svr;
// API endpoint
svr.Get("/api/hello", [](const auto &, auto &res) {
res.set_content(R"({"message":"Hello!"})", "application/json");
});
// Static file serving
svr.set_mount_point("/", "./public");
svr.listen("0.0.0.0", 8080);
Handlers take priority. The handler responds to /api/hello. For every other path, the server looks for a file in ./public.
Pass headers as the third argument to set_mount_point() and they get attached to every static file response. This is great for cache control.
svr.set_mount_point("/", "./public", {
{"Cache-Control", "max-age=3600"}
});
With this in place, the browser caches served files for one hour.
The cpp-httplib repository includes a Dockerfile built for static file serving. We also publish a pre-built image on Docker Hub, so you can get up and running with a single command.
> docker run -p 8080:80 -v ./my-site:/html yhirose4dockerhub/cpp-httplib-server
Serving HTTP on 0.0.0.0:80
Mount point: / -> ./html
Press Ctrl+C to shutdown gracefully...
192.168.65.1 - - [22/Feb/2026:12:00:00 +0000] "GET / HTTP/1.1" 200 256 "-" "Mozilla/5.0 ..."
192.168.65.1 - - [22/Feb/2026:12:00:00 +0000] "GET /style.css HTTP/1.1" 200 1024 "-" "Mozilla/5.0 ..."
192.168.65.1 - - [22/Feb/2026:12:00:01 +0000] "GET /favicon.ico HTTP/1.1" 404 152 "-" "Mozilla/5.0 ..."
Everything in your ./my-site directory gets served on port 8080. The access log follows the same format as NGINX, so you can see exactly what's happening.
You can now serve static files. A web server that delivers HTML, CSS, and JavaScript — built with this little code.
Next, let's encrypt your connections with HTTPS. We'll start by setting up a TLS library.
Next: TLS Setup