@@ -1494,6 +1494,297 @@ To test the above example, you can run the following command from a terminal:
14941494
14951495You can also check this example on [ github] ( https://github.com/etr/libhttpserver/blob/master/examples/deferred_with_accumulator.cpp ) .
14961496
1497+ #### Example of an empty response (204 No Content)
1498+ ``` cpp
1499+ #include < httpserver.hpp>
1500+
1501+ using namespace httpserver ;
1502+
1503+ class no_content_resource : public http_resource {
1504+ public:
1505+ std::shared_ptr<http_response> render_DELETE(const http_request&) {
1506+ // Return a 204 No Content response with no body
1507+ return std::make_shared<empty_response>(
1508+ http::http_utils::http_no_content);
1509+ }
1510+
1511+ std::shared_ptr<http_response> render_HEAD(const http_request&) {
1512+ // Return a HEAD-only response with headers but no body
1513+ auto response = std::make_shared<empty_response>(
1514+ http::http_utils::http_ok,
1515+ empty_response::HEAD_ONLY);
1516+ response->with_header("X-Total-Count", "42");
1517+ return response;
1518+ }
1519+ };
1520+
1521+ int main () {
1522+ webserver ws = create_webserver(8080);
1523+
1524+ no_content_resource ncr;
1525+ ws.register_resource("/items", &ncr);
1526+ ws.start(true);
1527+
1528+ return 0;
1529+ }
1530+ ```
1531+ To test the above example, you can run the following commands from a terminal:
1532+
1533+ curl -XDELETE -v localhost:8080/items
1534+ curl -I -v localhost:8080/items
1535+
1536+ You can also check this example on [github](https://github.com/etr/libhttpserver/blob/master/examples/empty_response_example.cpp).
1537+
1538+ #### Example of a scatter-gather (iovec) response
1539+ ```cpp
1540+ #include <httpserver.hpp>
1541+
1542+ using namespace httpserver;
1543+
1544+ class iovec_resource : public http_resource {
1545+ public:
1546+ std::shared_ptr<http_response> render_GET(const http_request&) {
1547+ // Build a response from multiple separate buffers without copying
1548+ std::vector<std::string> parts;
1549+ parts.push_back("{\"header\": \"value\", ");
1550+ parts.push_back("\"items\": [1, 2, 3], ");
1551+ parts.push_back("\"footer\": \"end\"}");
1552+
1553+ return std::make_shared<iovec_response>(
1554+ std::move(parts), 200, "application/json");
1555+ }
1556+ };
1557+
1558+ int main() {
1559+ webserver ws = create_webserver(8080);
1560+
1561+ iovec_resource ir;
1562+ ws.register_resource("/data", &ir);
1563+ ws.start(true);
1564+
1565+ return 0;
1566+ }
1567+ ```
1568+ To test the above example, you can run the following command from a terminal:
1569+
1570+ curl -XGET -v localhost:8080/data
1571+
1572+ You can also check this example on [ github] ( https://github.com/etr/libhttpserver/blob/master/examples/iovec_response_example.cpp ) .
1573+
1574+ #### Example of a pipe-based streaming response
1575+ ``` cpp
1576+ #include < cstring>
1577+ #include < thread>
1578+ #include < unistd.h>
1579+ #include < httpserver.hpp>
1580+
1581+ using namespace httpserver ;
1582+
1583+ class pipe_resource : public http_resource {
1584+ public:
1585+ std::shared_ptr<http_response> render_GET(const http_request&) {
1586+ int pipefd[ 2] ;
1587+ if (pipe(pipefd) == -1) {
1588+ return std::make_shared<string_response>("pipe failed", 500);
1589+ }
1590+
1591+ // Spawn a thread to write data into the pipe
1592+ std::thread writer([fd = pipefd[1]]() {
1593+ const char* messages[] = {"Hello ", "from ", "a pipe!\n"};
1594+ for (const char* msg : messages) {
1595+ ssize_t ret = write(fd, msg, strlen(msg));
1596+ (void)ret;
1597+ }
1598+ close (fd);
1599+ });
1600+ writer.detach();
1601+
1602+ // Return the read end of the pipe as the response
1603+ return std::make_shared<pipe_response>(pipefd[0], 200, "text/plain");
1604+ }
1605+ };
1606+
1607+ int main() {
1608+ webserver ws = create_webserver(8080);
1609+
1610+ pipe_resource pr;
1611+ ws.register_resource("/stream", &pr);
1612+ ws.start(true);
1613+
1614+ return 0;
1615+ }
1616+ ```
1617+ To test the above example, you can run the following command from a terminal:
1618+
1619+ curl -XGET -v localhost:8080/stream
1620+
1621+ You can also check this example on [github](https://github.com/etr/libhttpserver/blob/master/examples/pipe_response_example.cpp).
1622+
1623+ #### Example of a WebSocket echo server
1624+ ```cpp
1625+ #include <iostream>
1626+ #include <httpserver.hpp>
1627+
1628+ using namespace httpserver;
1629+
1630+ class echo_handler : public websocket_handler {
1631+ public:
1632+ void on_open(websocket_session& session) override {
1633+ std::cout << "WebSocket connection opened" << std::endl;
1634+ session.send_text("Welcome to the echo server!");
1635+ }
1636+
1637+ void on_message(websocket_session& session, const std::string& msg) override {
1638+ std::cout << "Received: " << msg << std::endl;
1639+ session.send_text("Echo: " + msg);
1640+ }
1641+
1642+ void on_close(websocket_session& session, uint16_t code, const std::string& reason) override {
1643+ std::cout << "WebSocket closed (code=" << code << ", reason=" << reason << ")" << std::endl;
1644+ }
1645+ };
1646+
1647+ int main() {
1648+ webserver ws = create_webserver(8080);
1649+
1650+ echo_handler handler;
1651+ ws.register_ws_resource("/ws", &handler);
1652+ ws.start(true);
1653+
1654+ return 0;
1655+ }
1656+ ```
1657+ Note: WebSocket support requires libmicrohttpd 1.0.0 built with WebSocket support. You can test this with any WebSocket client library or browser JavaScript: ` new WebSocket("ws://localhost:8080/ws") ` .
1658+
1659+ You can also check this example on [ github] ( https://github.com/etr/libhttpserver/blob/master/examples/websocket_echo.cpp ) .
1660+
1661+ #### Example of daemon introspection
1662+ ``` cpp
1663+ #include < iostream>
1664+ #include < httpserver.hpp>
1665+
1666+ using namespace httpserver ;
1667+
1668+ class hello_resource : public http_resource {
1669+ public:
1670+ std::shared_ptr<http_response> render_GET(const http_request&) {
1671+ return std::make_shared<string_response>("Hello, World!");
1672+ }
1673+ };
1674+
1675+ int main() {
1676+ // Use port 0 to let the OS assign an ephemeral port
1677+ webserver ws = create_webserver(0);
1678+
1679+ hello_resource hr;
1680+ ws.register_resource("/hello", &hr);
1681+ ws.start(false);
1682+
1683+ // Query daemon information
1684+ std::cout << "libmicrohttpd version: "
1685+ << http::http_utils::get_mhd_version() << std::endl;
1686+ std::cout << "Bound port: " << ws.get_bound_port() << std::endl;
1687+ std::cout << "Listen FD: " << ws.get_listen_fd() << std::endl;
1688+ std::cout << "Active connections: " << ws.get_active_connections() << std::endl;
1689+ std::cout << "HTTP 200 reason: "
1690+ << http::http_utils::reason_phrase(200) << std::endl;
1691+ std::cout << "HTTP 404 reason: "
1692+ << http::http_utils::reason_phrase(404) << std::endl;
1693+
1694+ ws.sweet_kill();
1695+ return 0;
1696+ }
1697+ ```
1698+ You can also check this example on [ github] ( https://github.com/etr/libhttpserver/blob/master/examples/daemon_info.cpp ) .
1699+
1700+ #### Example of an external event loop
1701+ ``` cpp
1702+ #include < csignal>
1703+ #include < iostream>
1704+ #include < httpserver.hpp>
1705+
1706+ using namespace httpserver ;
1707+
1708+ static volatile bool running = true ;
1709+
1710+ void signal_handler (int) { running = false; }
1711+
1712+ class hello_resource : public http_resource {
1713+ public:
1714+ std::shared_ptr<http_response> render_GET(const http_request&) {
1715+ return std::make_shared<string_response>("Hello from external event loop!");
1716+ }
1717+ };
1718+
1719+ int main() {
1720+ signal(SIGINT, signal_handler);
1721+
1722+ webserver ws = create_webserver(8080);
1723+
1724+ hello_resource hr;
1725+ ws.register_resource("/hello", &hr);
1726+ ws.start(false);
1727+
1728+ std::cout << "Server running on port " << ws.get_bound_port() << std::endl;
1729+
1730+ // Drive the event loop externally using run_wait
1731+ while (running) {
1732+ // Block for up to 1000ms waiting for HTTP activity
1733+ ws.run_wait(1000);
1734+
1735+ // You can do other work here between iterations
1736+ }
1737+
1738+ // Graceful shutdown: stop accepting new connections first
1739+ ws.quiesce();
1740+ ws.stop();
1741+
1742+ return 0;
1743+ }
1744+ ```
1745+ To test the above example, you can run the following command from a terminal:
1746+
1747+ curl -XGET -v localhost:8080/hello
1748+
1749+ You can also check this example on [github](https://github.com/etr/libhttpserver/blob/master/examples/external_event_loop.cpp).
1750+
1751+ #### Example of turbo mode with performance options
1752+ ```cpp
1753+ #include <httpserver.hpp>
1754+
1755+ using namespace httpserver;
1756+
1757+ class hello_resource : public http_resource {
1758+ public:
1759+ std::shared_ptr<http_response> render_GET(const http_request&) {
1760+ return std::make_shared<string_response>("Hello, turbo world!");
1761+ }
1762+ };
1763+
1764+ int main() {
1765+ // Create a high-performance server with turbo mode,
1766+ // suppressed date headers, and a thread pool.
1767+ webserver ws = create_webserver(8080)
1768+ .start_method(http::http_utils::INTERNAL_SELECT)
1769+ .max_threads(4)
1770+ .turbo()
1771+ .suppress_date_header()
1772+ .tcp_fastopen_queue_size(16)
1773+ .listen_backlog(128);
1774+
1775+ hello_resource hr;
1776+ ws.register_resource("/hello", &hr);
1777+ ws.start(true);
1778+
1779+ return 0;
1780+ }
1781+ ```
1782+ To test the above example, you can run the following command from a terminal:
1783+
1784+ curl -XGET -v localhost:8080/hello
1785+
1786+ You can also check this example on [ github] ( https://github.com/etr/libhttpserver/blob/master/examples/turbo_mode.cpp ) .
1787+
14971788[ Back to TOC] ( #table-of-contents )
14981789
14991790## Copying
0 commit comments