Redirecting to {base_path}/{default_lang}/...
- -"#, - default_lang = config.i18n.default_lang(), - base_path = base_path, - ); - - fs::write(out.join("index.html"), html)?; - Ok(()) -} - -/// Build Tera with embedded default templates, then override with any files -/// found in `{}", escape_html(code)),
- }
- }
-}
-
-fn escape_html(s: &str) -> String {
- s.replace('&', "&")
- .replace('<', "<")
- .replace('>', ">")
-}
diff --git a/docs-gen/src/serve.rs b/docs-gen/src/serve.rs
deleted file mode 100644
index 10b23f0..0000000
--- a/docs-gen/src/serve.rs
+++ /dev/null
@@ -1,340 +0,0 @@
-use crate::builder;
-use crate::config::SiteConfig;
-use crate::utils::copy_dir_recursive;
-use anyhow::{Context, Result};
-use notify::{Event, RecursiveMode, Watcher};
-use socket2::{Domain, Protocol, Socket, Type};
-use std::fs;
-use std::io::Write;
-use std::net::{TcpListener, TcpStream};
-use std::path::Path;
-use std::sync::mpsc;
-use std::sync::{Arc, Mutex};
-use std::thread;
-use std::time::Duration;
-use walkdir::WalkDir;
-
-/// Live-reload WebSocket script injected into every HTML page during serve.
-const LIVE_RELOAD_SCRIPT: &str = r#""#;
-
-/// Run the serve command: build, start HTTP + WebSocket servers, watch for changes.
-pub fn serve(src: &Path, port: u16, open_browser: bool) -> Result<()> {
- let config = SiteConfig::load(src)?;
- let base_path = config.site.base_path.clone();
- let ws_port = port + 1;
-
- // Create temp directory for serving
- let tmp_dir = tempfile::tempdir().context("Failed to create temp directory")?;
- let serve_root = tmp_dir.path().to_path_buf();
-
- println!("Serving from temp directory: {}", serve_root.display());
-
- // Initial build
- build_and_copy(src, &serve_root, &base_path, ws_port)?;
-
- // Track connected WebSocket clients
- let clients: ArcAll you need to get started with cpp-httplib is httplib.h and a C++ compiler. Let's download the file and get a Hello World server running.
You can download it directly from GitHub. Always use the latest version.
--curl -LO https://github.com/yhirose/cpp-httplib/raw/refs/tags/latest/httplib.h ++curl -LO https://github.com/yhirose/cpp-httplib/raw/refs/tags/latest/httplib.hcurl -LO https://github.com/yhirose/cpp-httplib/raw/refs/tags/latest/httplib.h @@ -121,18 +123,18 @@Hello World Server
Save the following code as
-server.cpp.-#include "httplib.h" - -int main() { - httplib::Server svr; - - svr.Get("/", [](const httplib::Request&, httplib::Response& res) { - res.set_content("Hello, World!", "text/plain"); - }); - - svr.listen("0.0.0.0", 8080); -} ++#include "httplib.h" + +int main() { + httplib::Server svr; + + svr.Get("/", [](const httplib::Request&, httplib::Response& res) { + res.set_content("Hello, World!", "text/plain"); + }); + + svr.listen("0.0.0.0", 8080); +}#include "httplib.h" @@ -151,17 +153,17 @@In just a few lines, you have a server that responds to HTTP requests.
Compiling and Running
The sample code in this tutorial is written in C++17 for cleaner, more concise code. cpp-httplib itself can compile with C++11 as well.
--# macOS -clang++ -std=c++17 -o server server.cpp - -# Linux -# `-pthread`: cpp-httplib uses threads internally -clang++ -std=c++17 -pthread -o server server.cpp - -# Windows (Developer Command Prompt) -# `/EHsc`: Enable C++ exception handling -cl /EHsc /std:c++17 server.cpp ++# macOS +clang++ -std=c++17 -o server server.cpp + +# Linux +# `-pthread`: cpp-httplib uses threads internally +clang++ -std=c++17 -pthread -o server server.cpp + +# Windows (Developer Command Prompt) +# `/EHsc`: Enable C++ exception handling +cl /EHsc /std:c++17 server.cpp# macOS @@ -177,12 +179,12 @@Once it compiles, run it.
--# macOS / Linux -./server - -# Windows -server.exe ++# macOS / Linux +./server + +# Windows +server.exe# macOS / Linux @@ -194,9 +196,9 @@Open
http://localhost:8080in your browser. If you see "Hello, World!", you're all set.You can also verify with
-curl.-curl http://localhost:8080/ -# Hello, World! +@@ -105,53 +107,53 @@+curl http://localhost:8080/ +# Hello, World!diff --git a/docs/en/tour/02-basic-client/index.html b/docs/en/tour/02-basic-client/index.html index a461643..48cab82 100644 --- a/docs/en/tour/02-basic-client/index.html +++ b/docs/en/tour/02-basic-client/index.html @@ -17,16 +17,16 @@curl http://localhost:8080/ @@ -214,7 +216,7 @@cpp-httplib isn't just for servers -- it also comes with a full HTTP client. Let's use
httplib::Clientto send GET and POST requests.Preparing a Test Server
To try out the client, you need a server that accepts requests. Save the following code, then compile and run it the same way you did in the previous chapter. We'll cover the server details in the next chapter.
--#include "httplib.h" -#include <iostream> - -int main() { - httplib::Server svr; - - svr.Get("/hi", [](const auto &, auto &res) { - res.set_content("Hello!", "text/plain"); - }); - - svr.Get("/search", [](const auto &req, auto &res) { - auto q = req.get_param_value("q"); - res.set_content("Query: " + q, "text/plain"); - }); - - svr.Post("/post", [](const auto &req, auto &res) { - res.set_content(req.body, "text/plain"); - }); - - svr.Post("/submit", [](const auto &req, auto &res) { - std::string result; - for (auto &[key, val] : req.params) { - result += key + " = " + val + "\n"; - } - res.set_content(result, "text/plain"); - }); - - svr.Post("/upload", [](const auto &req, auto &res) { - auto f = req.form.get_file("file"); - auto content = f.filename + " (" + std::to_string(f.content.size()) + " bytes)"; - res.set_content(content, "text/plain"); - }); - - svr.Get("/users/:id", [](const auto &req, auto &res) { - auto id = req.path_params.at("id"); - res.set_content("User ID: " + id, "text/plain"); - }); - - svr.Get(R"(/files/(\d+))", [](const auto &req, auto &res) { - auto id = req.matches[1]; - res.set_content("File ID: " + std::string(id), "text/plain"); - }); - - std::cout << "Listening on port 8080..." << std::endl; - svr.listen("0.0.0.0", 8080); -} ++#include "httplib.h" +#include <iostream> + +int main() { + httplib::Server svr; + + svr.Get("/hi", [](const auto &, auto &res) { + res.set_content("Hello!", "text/plain"); + }); + + svr.Get("/search", [](const auto &req, auto &res) { + auto q = req.get_param_value("q"); + res.set_content("Query: " + q, "text/plain"); + }); + + svr.Post("/post", [](const auto &req, auto &res) { + res.set_content(req.body, "text/plain"); + }); + + svr.Post("/submit", [](const auto &req, auto &res) { + std::string result; + for (auto &[key, val] : req.params) { + result += key + " = " + val + "\n"; + } + res.set_content(result, "text/plain"); + }); + + svr.Post("/upload", [](const auto &req, auto &res) { + auto f = req.form.get_file("file"); + auto content = f.filename + " (" + std::to_string(f.content.size()) + " bytes)"; + res.set_content(content, "text/plain"); + }); + + svr.Get("/users/:id", [](const auto &req, auto &res) { + auto id = req.path_params.at("id"); + res.set_content("User ID: " + id, "text/plain"); + }); + + svr.Get(R"(/files/(\d+))", [](const auto &req, auto &res) { + auto id = req.matches[1]; + res.set_content("File ID: " + std::string(id), "text/plain"); + }); + + std::cout << "Listening on port 8080..." << std::endl; + svr.listen("0.0.0.0", 8080); +}#include "httplib.h" @@ -204,19 +206,19 @@GET Request
Once the server is running, open a separate terminal and give it a try. Let's start with the simplest GET request.
--#include "httplib.h" -#include <iostream> - -int main() { - httplib::Client cli("http://localhost:8080"); - - auto res = cli.Get("/hi"); - if (res) { - std::cout << res->status << std::endl; // 200 - std::cout << res->body << std::endl; // Hello! - } -} ++#include "httplib.h" +#include <iostream> + +int main() { + httplib::Client cli("http://localhost:8080"); + + auto res = cli.Get("/hi"); + if (res) { + std::cout << res->status << std::endl; // 200 + std::cout << res->body << std::endl; // Hello! + } +}#include "httplib.h" @@ -235,9 +237,9 @@Pass the server address to the
httplib::Clientconstructor, then callGet()to send a request. You can retrieve the status code and body from the returnedres.Here's the equivalent
-curlcommand.-curl http://localhost:8080/hi -# Hello! ++curl http://localhost:8080/hi +# Hello!curl http://localhost:8080/hi @@ -246,18 +248,18 @@Checking the Response
A response contains header information in addition to the status code and body.
--auto res = cli.Get("/hi"); -if (res) { - // Status code - std::cout << res->status << std::endl; // 200 - - // Body - std::cout << res->body << std::endl; // Hello! - - // Headers - std::cout << res->get_header_value("Content-Type") << std::endl; // text/plain -} ++auto res = cli.Get("/hi"); +if (res) { + // Status code + std::cout << res->status << std::endl; // 200 + + // Body + std::cout << res->body << std::endl; // Hello! + + // Headers + std::cout << res->get_header_value("Content-Type") << std::endl; // text/plain +}auto res = cli.Get("/hi"); @@ -276,11 +278,11 @@
res->bodyis astd::string, so if you want to parse a JSON response, you can pass it directly to a JSON library like nlohmann/json.Query Parameters
To add query parameters to a GET request, you can either write them directly in the URL or use
-httplib::Params.-auto res = cli.Get("/search", httplib::Params{{"q", "cpp-httplib"}}); -if (res) { - std::cout << res->body << std::endl; // Query: cpp-httplib -} ++auto res = cli.Get("/search", httplib::Params{{"q", "cpp-httplib"}}); +if (res) { + std::cout << res->body << std::endl; // Query: cpp-httplib +}auto res = cli.Get("/search", httplib::Params{{"q", "cpp-httplib"}}); @@ -290,9 +292,9 @@-
httplib::Paramsautomatically URL-encodes special characters for you.-curl "http://localhost:8080/search?q=cpp-httplib" -# Query: cpp-httplib ++curl "http://localhost:8080/search?q=cpp-httplib" +# Query: cpp-httplibcurl "http://localhost:8080/search?q=cpp-httplib" @@ -301,11 +303,11 @@Path Parameters
When values are embedded directly in the URL path, no special client API is needed. Just pass the path to
-Get()as-is.-auto res = cli.Get("/users/42"); -if (res) { - std::cout << res->body << std::endl; // User ID: 42 -} ++auto res = cli.Get("/users/42"); +if (res) { + std::cout << res->body << std::endl; // User ID: 42 +}auto res = cli.Get("/users/42"); @@ -313,9 +315,9 @@ std::cout << res->body << std::endl; // User ID: 42 }--curl http://localhost:8080/users/42 -# User ID: 42 ++curl http://localhost:8080/users/42 +# User ID: 42curl http://localhost:8080/users/42 @@ -323,11 +325,11 @@The test server also has a
-/files/(\d+)route that uses a regex to accept numeric IDs only.-auto res = cli.Get("/files/42"); -if (res) { - std::cout << res->body << std::endl; // File ID: 42 -} ++auto res = cli.Get("/files/42"); +if (res) { + std::cout << res->body << std::endl; // File ID: 42 +}auto res = cli.Get("/files/42"); @@ -335,9 +337,9 @@ std::cout << res->body << std::endl; // File ID: 42 }--curl http://localhost:8080/files/42 -# File ID: 42 ++curl http://localhost:8080/files/42 +# File ID: 42curl http://localhost:8080/files/42 @@ -347,18 +349,18 @@Pass a non-numeric ID like
/files/abcand you'll get a 404. We'll cover how that works in the next chapter.Request Headers
To add custom HTTP headers, pass an
-httplib::Headersobject. This works with bothGet()andPost().-auto res = cli.Get("/hi", httplib::Headers{ - {"Authorization", "Bearer my-token"} -}); ++auto res = cli.Get("/hi", httplib::Headers{ + {"Authorization", "Bearer my-token"} +});auto res = cli.Get("/hi", httplib::Headers{ {"Authorization", "Bearer my-token"} });--curl -H "Authorization: Bearer my-token" http://localhost:8080/hi ++curl -H "Authorization: Bearer my-token" http://localhost:8080/hicurl -H "Authorization: Bearer my-token" http://localhost:8080/hi @@ -366,12 +368,12 @@POST Request
Let's POST some text data. Pass the body as the second argument to
-Post()and the Content-Type as the third.-auto res = cli.Post("/post", "Hello, Server!", "text/plain"); -if (res) { - std::cout << res->status << std::endl; // 200 - std::cout << res->body << std::endl; // Hello, Server! -} ++auto res = cli.Post("/post", "Hello, Server!", "text/plain"); +if (res) { + std::cout << res->status << std::endl; // 200 + std::cout << res->body << std::endl; // Hello, Server! +}auto res = cli.Post("/post", "Hello, Server!", "text/plain"); @@ -382,9 +384,9 @@The test server's
-/postendpoint echoes the body back, so you get the same string you sent.-curl -X POST -H "Content-Type: text/plain" -d "Hello, Server!" http://localhost:8080/post -# Hello, Server! ++curl -X POST -H "Content-Type: text/plain" -d "Hello, Server!" http://localhost:8080/post +# Hello, Server!curl -X POST -H "Content-Type: text/plain" -d "Hello, Server!" http://localhost:8080/post @@ -393,16 +395,16 @@Sending Form Data
You can send key-value pairs just like an HTML form. Use
-httplib::Paramsfor this.-auto res = cli.Post("/submit", httplib::Params{ - {"name", "Alice"}, - {"age", "30"} -}); -if (res) { - std::cout << res->body << std::endl; - // age = 30 - // name = Alice -} ++auto res = cli.Post("/submit", httplib::Params{ + {"name", "Alice"}, + {"age", "30"} +}); +if (res) { + std::cout << res->body << std::endl; + // age = 30 + // name = Alice +}auto res = cli.Post("/submit", httplib::Params{ @@ -417,8 +419,8 @@This sends the data in
-application/x-www-form-urlencodedformat.-curl -X POST -d "name=Alice&age=30" http://localhost:8080/submit ++curl -X POST -d "name=Alice&age=30" http://localhost:8080/submitcurl -X POST -d "name=Alice&age=30" http://localhost:8080/submit @@ -426,13 +428,13 @@POSTing a File
To upload a file, use
-httplib::UploadFormDataItemsto send it as multipart form data.-auto res = cli.Post("/upload", httplib::UploadFormDataItems{ - {"file", "Hello, File!", "hello.txt", "text/plain"} -}); -if (res) { - std::cout << res->body << std::endl; // hello.txt (12 bytes) -} ++auto res = cli.Post("/upload", httplib::UploadFormDataItems{ + {"file", "Hello, File!", "hello.txt", "text/plain"} +}); +if (res) { + std::cout << res->body << std::endl; // hello.txt (12 bytes) +}auto res = cli.Post("/upload", httplib::UploadFormDataItems{ @@ -444,8 +446,8 @@Each element in
-UploadFormDataItemshas four fields:{name, content, filename, content_type}.-curl -F "file=Hello, File!;filename=hello.txt;type=text/plain" http://localhost:8080/upload ++curl -F "file=Hello, File!;filename=hello.txt;type=text/plain" http://localhost:8080/uploadcurl -F "file=Hello, File!;filename=hello.txt;type=text/plain" http://localhost:8080/upload @@ -453,24 +455,24 @@Error Handling
Network communication can fail -- the server might not be reachable. Always check whether
-resis valid.-httplib::Client cli("http://localhost:9999"); // Non-existent port -auto res = cli.Get("/hi"); - -if (!res) { - // Connection error - std::cout << "Error: " << httplib::to_string(res.error()) << std::endl; - // Error: Connection - return 1; -} - -// If we reach here, we have a response -if (res->status != 200) { - std::cout << "HTTP Error: " << res->status << std::endl; - return 1; -} - -std::cout << res->body << std::endl; +@@ -105,8 +107,8 @@+httplib::Client cli("http://localhost:9999"); // Non-existent port +auto res = cli.Get("/hi"); + +if (!res) { + // Connection error + std::cout << "Error: " << httplib::to_string(res.error()) << std::endl; + // Error: Connection + return 1; +} + +// If we reach here, we have a response +if (res->status != 200) { + std::cout << "HTTP Error: " << res->status << std::endl; + return 1; +} + +std::cout << res->body << std::endl;diff --git a/docs/en/tour/03-basic-server/index.html b/docs/en/tour/03-basic-server/index.html index f40e292..27bacff 100644 --- a/docs/en/tour/03-basic-server/index.html +++ b/docs/en/tour/03-basic-server/index.html @@ -17,16 +17,16 @@httplib::Client cli("http://localhost:9999"); // Non-existent port @@ -507,7 +509,7 @@In the previous chapter, you sent requests from a client to a test server. Now let's walk through how that server actually works.
Starting the Server
Once you've registered your routes, call
-svr.listen()to start the server.-svr.listen("0.0.0.0", 8080); ++svr.listen("0.0.0.0", 8080);svr.listen("0.0.0.0", 8080); @@ -116,12 +118,12 @@
listen()is a blocking call. It won't return until the server stops. The server keeps running until you pressCtrl+Cin your terminal or callsvr.stop()from another thread.Routing
Routing is the heart of any server. It's how you tell cpp-httplib: when a request comes in for this URL with this HTTP method, run this code.
--httplib::Server svr; - -svr.Get("/hi", [](const httplib::Request &req, httplib::Response &res) { - res.set_content("Hello!", "text/plain"); -}); ++httplib::Server svr; + +svr.Get("/hi", [](const httplib::Request &req, httplib::Response &res) { + res.set_content("Hello!", "text/plain"); +});httplib::Server svr; @@ -133,11 +135,11 @@
svr.Get()registers a handler for GET requests. The first argument is the path, the second is the handler function. When a GET request arrives at/hi, your lambda runs.There's a method for each HTTP verb.
--svr.Get("/path", handler); // GET -svr.Post("/path", handler); // POST -svr.Put("/path", handler); // PUT -svr.Delete("/path", handler); // DELETE ++svr.Get("/path", handler); // GET +svr.Post("/path", handler); // POST +svr.Put("/path", handler); // PUT +svr.Delete("/path", handler); // DELETEsvr.Get("/path", handler); // GET @@ -147,10 +149,10 @@The handler signature is
-(const httplib::Request &req, httplib::Response &res). You can useautoto keep it short.-svr.Get("/hi", [](const auto &req, auto &res) { - res.set_content("Hello!", "text/plain"); -}); ++svr.Get("/hi", [](const auto &req, auto &res) { + res.set_content("Hello!", "text/plain"); +});svr.Get("/hi", [](const auto &req, auto &res) { @@ -163,11 +165,11 @@The first parameter
reqgives you everything the client sent.Body
-
req.bodyholds the request body as astd::string.-svr.Post("/post", [](const auto &req, auto &res) { - // Echo the body back to the client - res.set_content(req.body, "text/plain"); -}); ++svr.Post("/post", [](const auto &req, auto &res) { + // Echo the body back to the client + res.set_content(req.body, "text/plain"); +});svr.Post("/post", [](const auto &req, auto &res) { @@ -178,11 +180,11 @@Headers
Use
-req.get_header_value()to read a request header.-svr.Get("/check", [](const auto &req, auto &res) { - auto auth = req.get_header_value("Authorization"); - res.set_content("Auth: " + auth, "text/plain"); -}); ++svr.Get("/check", [](const auto &req, auto &res) { + auto auth = req.get_header_value("Authorization"); + res.set_content("Auth: " + auth, "text/plain"); +});svr.Get("/check", [](const auto &req, auto &res) { @@ -193,11 +195,11 @@Query Parameters and Form Data
-
req.get_param_value()retrieves a parameter by name. It works for both GET query parameters and POST form data.-svr.Get("/search", [](const auto &req, auto &res) { - auto q = req.get_param_value("q"); - res.set_content("Query: " + q, "text/plain"); -}); ++svr.Get("/search", [](const auto &req, auto &res) { + auto q = req.get_param_value("q"); + res.set_content("Query: " + q, "text/plain"); +});svr.Get("/search", [](const auto &req, auto &res) { @@ -208,14 +210,14 @@A request to
/search?q=cpp-httplibgives you"cpp-httplib"forq.To loop over all parameters, use
-req.params.-svr.Post("/submit", [](const auto &req, auto &res) { - std::string result; - for (auto &[key, val] : req.params) { - result += key + " = " + val + "\n"; - } - res.set_content(result, "text/plain"); -}); ++svr.Post("/submit", [](const auto &req, auto &res) { + std::string result; + for (auto &[key, val] : req.params) { + result += key + " = " + val + "\n"; + } + res.set_content(result, "text/plain"); +});svr.Post("/submit", [](const auto &req, auto &res) { @@ -229,12 +231,12 @@File Uploads
Files uploaded via multipart form data are available through
-req.form.get_file().-svr.Post("/upload", [](const auto &req, auto &res) { - auto f = req.form.get_file("file"); - auto content = f.filename + " (" + std::to_string(f.content.size()) + " bytes)"; - res.set_content(content, "text/plain"); -}); ++svr.Post("/upload", [](const auto &req, auto &res) { + auto f = req.form.get_file("file"); + auto content = f.filename + " (" + std::to_string(f.content.size()) + " bytes)"; + res.set_content(content, "text/plain"); +});svr.Post("/upload", [](const auto &req, auto &res) { @@ -247,11 +249,11 @@
f.filenamegives you the filename, andf.contentgives you the file data.Path Parameters
Sometimes you want to capture part of the URL as a variable -- for example, the
-42in/users/42. Use the:paramsyntax to do that.-svr.Get("/users/:id", [](const auto &req, auto &res) { - auto id = req.path_params.at("id"); - res.set_content("User ID: " + id, "text/plain"); -}); ++svr.Get("/users/:id", [](const auto &req, auto &res) { + auto id = req.path_params.at("id"); + res.set_content("User ID: " + id, "text/plain"); +});svr.Get("/users/:id", [](const auto &req, auto &res) { @@ -262,12 +264,12 @@A request to
/users/42gives you"42"fromreq.path_params.at("id")./users/100gives you"100".You can capture multiple segments at once.
--svr.Get("/users/:user_id/posts/:post_id", [](const auto &req, auto &res) { - auto user_id = req.path_params.at("user_id"); - auto post_id = req.path_params.at("post_id"); - res.set_content("User: " + user_id + ", Post: " + post_id, "text/plain"); -}); ++svr.Get("/users/:user_id/posts/:post_id", [](const auto &req, auto &res) { + auto user_id = req.path_params.at("user_id"); + auto post_id = req.path_params.at("post_id"); + res.set_content("User: " + user_id + ", Post: " + post_id, "text/plain"); +});svr.Get("/users/:user_id/posts/:post_id", [](const auto &req, auto &res) { @@ -279,12 +281,12 @@Regex Patterns
You can also write a regular expression directly in the path instead of
-:param. Capture group values are available viareq.matches, which is astd::smatch.-// Only accept numeric IDs -svr.Get(R"(/files/(\d+))", [](const auto &req, auto &res) { - auto id = req.matches[1]; // First capture group - res.set_content("File ID: " + std::string(id), "text/plain"); -}); ++// Only accept numeric IDs +svr.Get(R"(/files/(\d+))", [](const auto &req, auto &res) { + auto id = req.matches[1]; // First capture group + res.set_content("File ID: " + std::string(id), "text/plain"); +});// Only accept numeric IDs @@ -299,10 +301,10 @@The second parameter
resis how you send data back to the client.Body and Content-Type
-
res.set_content()sets the body and Content-Type. That's all you need for a 200 response.-svr.Get("/hi", [](const auto &req, auto &res) { - res.set_content("Hello!", "text/plain"); -}); ++svr.Get("/hi", [](const auto &req, auto &res) { + res.set_content("Hello!", "text/plain"); +});svr.Get("/hi", [](const auto &req, auto &res) { @@ -312,11 +314,11 @@Status Code
To return a different status code, assign to
-res.status.-svr.Get("/not-found", [](const auto &req, auto &res) { - res.status = 404; - res.set_content("Not found", "text/plain"); -}); ++svr.Get("/not-found", [](const auto &req, auto &res) { + res.status = 404; + res.set_content("Not found", "text/plain"); +});svr.Get("/not-found", [](const auto &req, auto &res) { @@ -327,11 +329,11 @@Response Headers
Add response headers with
-res.set_header().-svr.Get("/with-header", [](const auto &req, auto &res) { - res.set_header("X-Custom", "my-value"); - res.set_content("Hello!", "text/plain"); -}); ++svr.Get("/with-header", [](const auto &req, auto &res) { + res.set_header("X-Custom", "my-value"); + res.set_content("Hello!", "text/plain"); +});svr.Get("/with-header", [](const auto &req, auto &res) { @@ -343,10 +345,10 @@Walking Through the Test Server
Now let's use what we've learned to read through the test server from the previous chapter.
GET /hi
--svr.Get("/hi", [](const auto &, auto &res) { - res.set_content("Hello!", "text/plain"); -}); ++svr.Get("/hi", [](const auto &, auto &res) { + res.set_content("Hello!", "text/plain"); +});svr.Get("/hi", [](const auto &, auto &res) { @@ -356,11 +358,11 @@The simplest possible handler. We don't need any information from the request, so the
reqparameter is left unnamed. It just returns"Hello!".GET /search
--svr.Get("/search", [](const auto &req, auto &res) { - auto q = req.get_param_value("q"); - res.set_content("Query: " + q, "text/plain"); -}); ++svr.Get("/search", [](const auto &req, auto &res) { + auto q = req.get_param_value("q"); + res.set_content("Query: " + q, "text/plain"); +});svr.Get("/search", [](const auto &req, auto &res) { @@ -371,10 +373,10 @@
req.get_param_value("q")pulls out the query parameterq. A request to/search?q=cpp-httplibreturns"Query: cpp-httplib".POST /post
--svr.Post("/post", [](const auto &req, auto &res) { - res.set_content(req.body, "text/plain"); -}); ++svr.Post("/post", [](const auto &req, auto &res) { + res.set_content(req.body, "text/plain"); +});svr.Post("/post", [](const auto &req, auto &res) { @@ -384,14 +386,14 @@An echo server. Whatever body the client sends,
req.bodyholds it, and we send it straight back.POST /submit
--svr.Post("/submit", [](const auto &req, auto &res) { - std::string result; - for (auto &[key, val] : req.params) { - result += key + " = " + val + "\n"; - } - res.set_content(result, "text/plain"); -}); ++svr.Post("/submit", [](const auto &req, auto &res) { + std::string result; + for (auto &[key, val] : req.params) { + result += key + " = " + val + "\n"; + } + res.set_content(result, "text/plain"); +});svr.Post("/submit", [](const auto &req, auto &res) { @@ -405,12 +407,12 @@Loops over the form data in
req.paramsusing structured bindings (auto &[key, val]) to unpack each key-value pair.POST /upload
--svr.Post("/upload", [](const auto &req, auto &res) { - auto f = req.form.get_file("file"); - auto content = f.filename + " (" + std::to_string(f.content.size()) + " bytes)"; - res.set_content(content, "text/plain"); -}); ++svr.Post("/upload", [](const auto &req, auto &res) { + auto f = req.form.get_file("file"); + auto content = f.filename + " (" + std::to_string(f.content.size()) + " bytes)"; + res.set_content(content, "text/plain"); +});svr.Post("/upload", [](const auto &req, auto &res) { @@ -422,11 +424,11 @@Receives a file uploaded via multipart form data.
req.form.get_file("file")fetches the field named"file", and we respond with the filename and size.GET /users/:id
--svr.Get("/users/:id", [](const auto &req, auto &res) { - auto id = req.path_params.at("id"); - res.set_content("User ID: " + id, "text/plain"); -}); ++svr.Get("/users/:id", [](const auto &req, auto &res) { + auto id = req.path_params.at("id"); + res.set_content("User ID: " + id, "text/plain"); +});svr.Get("/users/:id", [](const auto &req, auto &res) { @@ -437,11 +439,11 @@
:idis the path parameter.req.path_params.at("id")retrieves its value./users/42gives you"42",/users/alicegives you"alice".GET /files/(\d+)
--svr.Get(R"(/files/(\d+))", [](const auto &req, auto &res) { - auto id = req.matches[1]; - res.set_content("File ID: " + std::string(id), "text/plain"); -}); +@@ -105,18 +107,18 @@+svr.Get(R"(/files/(\d+))", [](const auto &req, auto &res) { + auto id = req.matches[1]; + res.set_content("File ID: " + std::string(id), "text/plain"); +});diff --git a/docs/en/tour/04-static-file-server/index.html b/docs/en/tour/04-static-file-server/index.html index b4f0589..d6a0bbd 100644 --- a/docs/en/tour/04-static-file-server/index.html +++ b/docs/en/tour/04-static-file-server/index.html @@ -17,16 +17,16 @@svr.Get(R"(/files/(\d+))", [](const auto &req, auto &res) { @@ -462,7 +464,7 @@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.The basics of set_mount_point
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); -} ++#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); +}#include "httplib.h" @@ -134,21 +136,21 @@The first argument is the URL mount point. The second is the local directory path. In this example, requests to
/are served from the./htmldirectory.Let's try it out. First, create an
-htmldirectory and add anindex.htmlfile.-mkdir html ++mkdir htmlmkdir 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> ++<!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><!DOCTYPE html> @@ -162,9 +164,9 @@Compile and start the server.
--g++ -std=c++17 -o server server.cpp -pthread -./server ++g++ -std=c++17 -o server server.cpp -pthread +./serverg++ -std=c++17 -o server server.cpp -pthread @@ -173,12 +175,12 @@Open
http://localhost:8080in your browser. You should see the contents ofhtml/index.html. Visitinghttp://localhost:8080/index.htmlreturns 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 -} ++httplib::Client cli("http://localhost:8080"); +auto res = cli.Get("/"); +if (res) { + std::cout << res->body << std::endl; // HTML is displayed +}httplib::Client cli("http://localhost:8080"); @@ -187,8 +189,8 @@ std::cout << res->body << std::endl; // HTML is displayed }--curl http://localhost:8080 ++curl http://localhost:8080curl http://localhost:8080 @@ -196,10 +198,10 @@Multiple mount points
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"); +