### Basic HTTP Server Setup Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/http-server.md Demonstrates creating a basic HTTP server, configuring a GET route, binding to an address and port, and starting the server with signal handling for graceful shutdown. ```cpp #include "glaze/net/http_server.hpp" #include glz::http_server server; // Configure routes server.get("/hello", [](const glz::request& /*req*/, glz::response& res) { res.body("Hello, World!"); }); // Note: start() is non-blocking; block main until shutdown server.bind("127.0.0.1", 8080) .with_signals(); // handle Ctrl+C (SIGINT) std::cout << "Server running on http://127.0.0.1:8080\n"; std::cout << "Press Ctrl+C to stop\n"; server.start(); server.wait_for_signal(); ``` -------------------------------- ### Basic HTTP Server Setup Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/http-server.md Demonstrates how to create a basic HTTP server, define a GET route, bind it to an address and port, and start the server with signal handling for graceful shutdown. ```APIDOC ## Basic HTTP Server Setup ### Description This example shows how to create a simple HTTP server, register a route for `/hello` that responds with "Hello, World!", bind the server to localhost on port 8080, and start it, including handling SIGINT (Ctrl+C) for shutdown. ### Method `glz::http_server` ### Endpoint `/hello` (GET) ### Request Example (No request body specified for this GET route) ### Response #### Success Response (200) - **body** (string) - "Hello, World!" ### Code Example ```cpp #include "glaze/net/http_server.hpp" #include glz::http_server server; // Configure routes server.get("/hello", [](const glz::request& /*req*/, glz::response& res) { res.body("Hello, World!"); }); // Note: start() is non-blocking; block main until shutdown server.bind("127.0.0.1", 8080) .with_signals(); // handle Ctrl+C (SIGINT) std::cout << "Server running on http://127.0.0.1:8080\n"; std::cout << "Press Ctrl+C to stop\n"; server.start(); server.wait_for_signal(); ``` ``` -------------------------------- ### Setup HTTPS Server Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/advanced-networking.md Configure and start an HTTPS server. Ensure you have server certificate and key files. Client certificate verification can be optionally enabled. ```cpp #include "glaze/net/http_server.hpp" // Create HTTPS server (EnableTLS template parameter) glz::https_server server; // or glz::http_server // Load SSL certificates server.load_certificate("server-cert.pem", "server-key.pem"); // Configure SSL options server.set_ssl_verify_mode(0); // No client certificate verification // Optional: Require client certificates // server.set_ssl_verify_mode(SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT); // Setup routes as normal server.get("/secure-data", [](const glz::request& req, glz::response& res) { res.json({ {"secure", true}, {"client_ip", req.remote_ip}, {"timestamp", std::time(nullptr)} }); }); server.bind(8443).with_signals(); // Standard HTTPS port server.start(); server.wait_for_signal(); ``` -------------------------------- ### Mixed HTTP/HTTPS Server Setup Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/tls-support.md Example demonstrating how to run both HTTP and HTTPS servers concurrently on different ports. ```APIDOC ## DELETE /api/users/{id} ### Description Deletes a user from the system. ### Method DELETE ### Endpoint /api/users/{id} ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the user to delete. ### Response #### Success Response (204) No content is returned upon successful deletion. #### Response Example (No content) ``` -------------------------------- ### Recommended Glaze Asio Setup Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/asio-setup.md Use `glaze_setup_asio()` to automatically select and link an Asio backend. This ensures CMake and headers are in sync, preventing potential issues with multiple Asio installations. ```cmake find_package(glaze CONFIG REQUIRED) # or FetchContent_MakeAvailable(glaze) glaze_setup_asio() # picks Boost / standalone / bundled Asio add_executable(myapp main.cpp) target_link_libraries(myapp PRIVATE glaze::glaze glaze::asio) ``` -------------------------------- ### Mixed HTTP and HTTPS Server Setup Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/tls-support.md Example demonstrating how to run both an HTTP server on port 8080 and an HTTPS server on port 8443 concurrently using separate threads. ```cpp #include "glaze/net/http_server.hpp" int main() { // HTTP server for public content glz::http_server<> http_server; http_server.get("/", [](const glz::request& req, glz::response& res) { res.body("Public HTTP content"); }); // HTTPS server for secure content glz::https_server https_server; https_server.load_certificate("cert.pem", "key.pem") .get("/secure", [](const glz::request& req, glz::response& res) { res.body("Secure HTTPS content"); }); // Start both servers std::thread http_thread([&]() { http_server.bind(8080).start(); }); std::thread https_thread([&]() { https_server.bind(8443).start(); }); http_thread.join(); https_thread.join(); return 0; } ``` -------------------------------- ### Start Simple HTTP Server with Signal Handling Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/http-server.md A basic HTTP server setup that includes signal handling for graceful shutdown. It configures a single route and binds to port 8080. ```cpp // Simple server with signal handling int main() { glz::http_server server; // Configure routes server.get("/api/hello", [](const glz::request&, glz::response& res) { res.json({{"message", "Hello, World!"}}); }); // Bind and enable signal handling server.bind(8080) .with_signals(); // Start server server.start(); // Wait for shutdown signal server.wait_for_signal(); return 0; } ``` -------------------------------- ### Basic HTTP Requests with Glaze Client Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/advanced-networking.md Demonstrates making GET and POST requests using the Glaze HTTP client. Includes examples for sending JSON data and custom headers. Ensure the 'glaze/net/http_client.hpp' header is included. ```cpp #include "glaze/net/http_client.hpp" glz::http_client client; // GET request auto response = client.get("https://api.example.com/users"); if (response && response->status_code == 200) { std::cout << "Response: " << response->response_body << std::endl; } // POST request with JSON User new_user{0, "John Doe", "john@example.com"}; auto create_response = client.post_json("https://api.example.com/users", new_user); // POST with custom headers std::unordered_map headers = { {"Authorization", "Bearer " + token}, {"Content-Type", "application/json"} }; auto auth_response = client.post("https://api.example.com/data", json_data, headers); ``` -------------------------------- ### Complete Glaze HTTP Server Example Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/asio-setup.md A full example demonstrating a Glaze HTTP server with a '/hello' endpoint. This includes C++ source and CMake build configuration. ```cpp // main.cpp #include "glaze/net/http_server.hpp" #include int main() { glz::http_server server; server.get("/hello", [](const glz::request&, glz::response& res) { res.json({{"message", "Hello from Glaze!"}}); }); server.bind("127.0.0.1", 8080).with_signals(); std::cout << "Server running on http://127.0.0.1:8080\n"; server.start(); server.wait_for_signal(); return 0; } ``` ```cmake # CMakeLists.txt cmake_minimum_required(VERSION 3.20) project(hello_server LANGUAGES CXX) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) include(FetchContent) FetchContent_Declare( glaze GIT_REPOSITORY https://github.com/stephenberry/glaze.git GIT_TAG main GIT_SHALLOW TRUE ) FetchContent_Declare( asio GIT_REPOSITORY https://github.com/chriskohlhoff/asio.git GIT_TAG asio-1-36-0 GIT_SHALLOW TRUE ) FetchContent_MakeAvailable(glaze asio) add_executable(hello_server main.cpp) target_link_libraries(hello_server PRIVATE glaze::glaze) target_include_directories(hello_server PRIVATE ${asio_SOURCE_DIR}/asio/include) if(WIN32) target_link_libraries(hello_server PRIVATE ws2_32) endif() if(MSVC) target_compile_options(hello_server PRIVATE /Zc:preprocessor) endif() ``` -------------------------------- ### Ubuntu/Debian Manual Glaze Installation Source: https://github.com/stephenberry/glaze/blob/main/docs/installation.md Steps to manually install Glaze on Ubuntu/Debian systems by cloning the repository, building with CMake, and installing. ```bash # Install dependencies sudo apt-get update sudo apt-get install build-essential cmake git # Clone and install git clone https://github.com/stephenberry/glaze.git cd glaze mkdir build && cd build cmake .. sudo make install ``` -------------------------------- ### Compile-Time Typed JSON-RPC 2.0 Client/Server Example Source: https://github.com/stephenberry/glaze/blob/main/docs/rpc/json-rpc.md Demonstrates the setup and usage of a compile-time typed JSON-RPC 2.0 server and client in C++. Includes defining request/response structures, registering server methods with callbacks, and making client requests with response handling. ```C++ struct foo_params { int foo_a{}; std::string foo_b{}; }; struct foo_result { bool foo_c{}; std::string foo_d{}; auto operator<=>(const foo_result&) const = default; }; struct bar_params { int bar_a; std::string bar_b; }; struct bar_result { bool bar_c{}; std::string bar_d{}; auto operator<=>(const bar_result&) const = default; }; namespace rpc = glz::rpc; int main() { rpc::server, rpc::method<"bar", bar_params, bar_result>> server; rpc::client, rpc::method<"bar", bar_params, bar_result>> client; // One long living callback per method for the server server.on<"foo">([](foo_params const& params) -> glz::expected { // access to member variables for the request `foo` // params.foo_a // params.foo_b if( params.foo_a != 0) return foo_result{.foo_c = true, .foo_d = "new world"}; else // Or return an error: return glz::unexpected{rpc::error{rpc::error_e::server_error_lower, {}, "my error"}}; }); server.on<"bar">([](bar_params const& params) { return bar_result{.bar_c = true, .bar_d = "new world"}; }); std::string uuid{"42"}; // One callback per client request auto [request_str, inserted] = client.request<"foo"> uuid, foo_params{.foo_a = 1337, .foo_b = "hello world"}, [](glz::expected value, rpc::id_t id) -> void { // Access to value/error and/or id }); // request_str: R"({\"jsonrpc\":\"2.0\",\"method\":\"foo\",\"params\":{\"foo_a\":1337,\"foo_b\":\"hello world\"},\"id\":\"42\"})" // send request_str over your communication protocol to the server // you can assign timeout for the request in your event loop auto timeout = [uuid, &client]() { decltype(auto) map = client.get_request_map<"foo">(); if (map.contains(uuid)) map.erase(uuid); }; timeout(); // Call the server callback for method `foo` // Returns response json string since the request_str can withhold batch of requests. // If the request is a notification (no `id` in request) a response will not be generated. // For convenience, you can serialize the response yourself and get the responses as following: // auto response_vector = server.call("..."); // std::string response = glz::write_json(response_vector); std::string response = server.call(request_str); assert(response == R"({\"jsonrpc\":\"2.0\",\"result\":{\"foo_c\":true,\"foo_d\":\"new world\"},\"id\":\"42\"})"); // Call the client callback for method `foo` with the provided results // This will automatically remove the previously assigned callback client.call(response); // This would return an internal error since the `id` is still not in the request map auto err = client.call(response); } ``` -------------------------------- ### YAML Output Example Source: https://github.com/stephenberry/glaze/blob/main/docs/yaml.md This is an example of the YAML output generated from the app_config structure. ```yaml host: "127.0.0.1" port: 8080 retry: attempts: 5 backoff_ms: 250 features: - metrics ``` -------------------------------- ### Install Standalone ASIO via Package Managers Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/asio-setup.md Commands to install the standalone ASIO library using various package managers. ```bash # macOS (Homebrew) brew install asio # Ubuntu/Debian sudo apt-get install libasio-dev # Arch Linux sudo pacman -S asio # vcpkg vcpkg install asio # Conan conan install asio/1.28.0@ ``` -------------------------------- ### Global Middleware Example Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/http-router.md Register global middleware using router.use(). This example shows logging and authentication middleware. ```cpp // Logging middleware router.use([](const glz::request& req, glz::response& res) { auto start = std::chrono::high_resolution_clock::now(); // Log request std::cout << glz::to_string(req.method) << " " << req.target << " from " << req.remote_ip << std::endl; }); // Authentication middleware router.use([](const glz::request& req, glz::response& res) { if (requires_auth(req.target)) { auto auth_header = req.headers.find("Authorization"); if (auth_header == req.headers.end()) { res.status(401).json({{"error", "Authentication required"}}); return; } if (!validate_token(auth_header->second)) { res.status(403).json({{"error", "Invalid token"}}); return; } } }); ``` -------------------------------- ### Install Boost.Asio via Package Managers Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/asio-setup.md Commands to install the Boost library, which includes Boost.Asio, using various package managers. ```bash # macOS (Homebrew) brew install boost # Ubuntu/Debian sudo apt-get install libboost-system-dev # Arch Linux sudo pacman -S boost # vcpkg vcpkg install boost-asio # Conan conan install boost/1.83.0@ ``` -------------------------------- ### Asynchronous Requests with Callbacks Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/http-client.md Shows how to perform asynchronous HTTP requests using callbacks. This example includes an async GET request and an async JSON POST request, both with their results handled by lambda functions. ```cpp #include "glaze/net/http_client.hpp" #include int main() { glz::http_client client; // Async GET with callback client.get_async("https://api.github.com/users/octocat", {}, [](std::expected result) { if (result) { std::cout << "Async GET completed! Status: " << result->status_code << std::endl; } else { std::cerr << "Async GET failed: " << result.error().message() << std::endl; } }); // Async JSON POST with callback struct Data { int value = 42; }; Data data; client.post_json_async("https://httpbin.org/post", data, {}, [](std::expected result) { if (result) { std::cout << "Async JSON POST completed! Status: " << result->status_code << std::endl; } else { std::cerr << "Async JSON POST failed: " << result.error().message() << std::endl; } }); // Keep the main thread alive long enough for async operations to complete std::this_thread::sleep_for(std::chrono::seconds(2)); return 0; } ``` -------------------------------- ### Build JSON-RPC Example Source: https://github.com/stephenberry/glaze/blob/main/examples/CMakeLists.txt Configure a CMake project to build an executable for the JSON-RPC example, linking against the Glaze library. ```cmake project(jsonrpc_example) add_executable(json-rpc EXCLUDE_FROM_ALL) target_sources(json-rpc PRIVATE json-rpc.cpp) target_link_libraries( json-rpc PRIVATE glaze::glaze) ``` -------------------------------- ### Conan Install and Build Commands Source: https://github.com/stephenberry/glaze/blob/main/docs/installation.md Commands to install Glaze using Conan and build your project with CMake presets. ```bash conan install . --build=missing cmake --preset conan-default cmake --build --preset conan-release ``` -------------------------------- ### Zero-Copy Request Handler Example Source: https://github.com/stephenberry/glaze/blob/main/docs/rpc/repe-buffer.md An example demonstrating how to handle incoming requests using zero-copy parsing and a response builder. ```APIDOC ## Example: Zero-Copy Request Handler ### Description This example shows a complete handler function that parses a request zero-copy, routes it based on the query, and constructs a response. ### Method (Function definition, not an HTTP method) ### Endpoint N/A (Illustrative function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **request** (std::span) - The raw bytes of the incoming request. - **response_buffer** (std::string&) - The string buffer to write the generated response to. ### Request Example ```cpp void handle_request(std::span request, std::string& response_buffer) { // Zero-copy parse auto result = glz::repe::parse_request(request); if (!result) { glz::repe::encode_error_buffer( glz::error_code::parse_error, response_buffer, "Failed to parse request" ); return; } const auto& req = result.request; glz::repe::response_builder resp{response_buffer}; // Route based on query (no allocation - query is a view) if (req.query == "/api/status") { resp.reset(req); resp.set_body_raw(R"({\"status\": \"ok\"})", glz::repe::body_format::JSON); } else if (req.query == "/api/echo") { // Echo back the body resp.reset(req); resp.set_body_raw(req.body, glz::repe::body_format::JSON); } else { resp.reset(req); resp.set_error(glz::error_code::method_not_found, "Unknown endpoint"); } } ``` ### Response (The response is written into the `response_buffer`) #### Success Response (A valid REPE response, either success or error, written to `response_buffer`) #### Response Example (Example of a success response for `/api/status`) ```json { "status": "ok" } ``` ``` -------------------------------- ### Implement Echo Client Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/websocket-client.md A complete example demonstrating a WebSocket client that echoes received messages. ```cpp #include "glaze/net/websocket_client.hpp" #include #include int main() { glz::websocket_client client; client.on_open([&client]() { std::cout << "Connected! Sending message..." << std::endl; client.send("Hello, WebSocket!"); }); client.on_message([&client](std::string_view message, glz::ws_opcode opcode) { if (opcode == glz::ws_opcode::text) { std::cout << "Echo received: " << message << std::endl; client.close(); } }); client.on_close([&client](glz::ws_close_code code, std::string_view reason) { std::cout << "Connection closed" << std::endl; client.context()->stop(); }); client.on_error([](std::error_code ec) { std::cerr << "Error: " << ec.message() << std::endl; }); client.connect("ws://localhost:8080/ws"); client.run(); return 0; } ``` -------------------------------- ### Build Wrapping Middleware Example Source: https://github.com/stephenberry/glaze/blob/main/examples/CMakeLists.txt Configure a CMake project to build an executable for the wrapping middleware example, linking against the Glaze library. ```cmake add_executable(wrapping_middleware_example EXCLUDE_FROM_ALL) target_sources(wrapping_middleware_example PRIVATE wrapping_middleware_example.cpp) target_link_libraries(wrapping_middleware_example PRIVATE glaze::glaze) ``` -------------------------------- ### Docker Development Environment Setup Source: https://github.com/stephenberry/glaze/blob/main/docs/p2996-reflection.md Dockerfile for building a container with Bloomberg clang-p2996 support. ```dockerfile FROM ubuntu:22.04 # Install build dependencies RUN apt-get update && apt-get install -y \ git cmake ninja-build python3 # Clone and build Bloomberg clang-p2996 RUN git clone https://github.com/bloomberg/clang-p2996.git /opt/llvm-project WORKDIR /opt/llvm-project RUN cmake -S llvm -B build -G Ninja \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_ENABLE_PROJECTS="clang" \ -DLLVM_ENABLE_RUNTIMES="libcxx;libcxxabi" RUN cmake --build build ``` -------------------------------- ### Example: Message Router Source: https://github.com/stephenberry/glaze/blob/main/docs/rpc/repe-buffer.md An example demonstrating how to use `extract_query` to route messages based on the query string. ```APIDOC ## Example: Message Router ### Description This example illustrates a message router that uses `extract_query` to determine the appropriate service for handling an incoming message. ### Method (Function definition, not an HTTP method) ### Endpoint N/A (Illustrative function) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **data** (const char*) - Pointer to the raw message data. - **size** (size_t) - The size of the message data. ### Request Example ```cpp #include "glaze/rpc/repe/buffer.hpp" void route_message(const char* data, size_t size) { // Extract query without full deserialization auto query = glz::repe::extract_query(data, size); if (query.empty()) { // Invalid message return; } // Route based on query prefix if (query.starts_with("/users/")) { users_service.forward(data, size); } else if (query.starts_with("/orders/")) { orders_service.forward(data, size); } else { // Unknown route } } ``` ### Response (No direct response, but messages are forwarded to appropriate services) #### Success Response (N/A) #### Response Example (N/A) ``` -------------------------------- ### Using Boost.Asio Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/asio-setup.md Links Glaze and the Boost.Asio system component to your application. Requires Boost to be installed and configured. ```cmake find_package(Boost REQUIRED COMPONENTS system) target_link_libraries(myapp PRIVATE glaze::glaze Boost::system) ``` -------------------------------- ### Register Basic GET and POST Routes Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/http-server.md Defines handlers for GET requests to retrieve users and POST requests to create users, including JSON parsing and error handling. ```cpp // GET route server.get("/users", [](const glz::request& req, glz::response& res) { res.json(get_all_users()); }); // POST route server.post("/users", [](const glz::request& req, glz::response& res) { User user; if (auto ec = glz::read_json(user, req.body)) { res.status(400).body("Invalid JSON"); return; } create_user(user); res.status(201).json(user); }); ``` -------------------------------- ### Implement Plugin Info Export Source: https://github.com/stephenberry/glaze/blob/main/docs/rpc/repe-plugin.md Example implementation of the required plugin info export using a static struct. ```c static const repe_plugin_data plugin_info = { .name = "calculator", .version = "1.0.0", .root_path = "/calculator" }; const repe_plugin_data* repe_plugin_info(void) { return &plugin_info; } ``` -------------------------------- ### Install OpenSSL Development Libraries Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/tls-support.md Commands to install OpenSSL development libraries on Ubuntu/Debian, macOS with Homebrew, and Windows using vcpkg. ```bash # On Ubuntu/Debian sudo apt-get install libssl-dev # On macOS with Homebrew brew install openssl export PKG_CONFIG_PATH="/opt/homebrew/lib/pkgconfig" # On Windows vcpkg install openssl ``` -------------------------------- ### Connecting to a Server Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/websocket-client.md Defines the connect method signature and provides examples for both ws and wss protocols. ```cpp void connect(std::string_view url); ``` ```cpp client.connect("ws://example.com:8080/chat"); client.connect("wss://secure-api.example.com/stream"); ``` -------------------------------- ### Start Glaze Server with Signal Handling Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/http-examples.md This code initializes and starts a Glaze server on port 8080, enabling signal handling for graceful shutdown. It includes informational output to the console and a blocking call to wait for the shutdown signal. ```cpp std::cout << "Authentication server running on http://localhost:8080" << std::endl; std::cout << "Test credentials: admin/admin123 or user/user123" << std::endl; std::cout << "Press Ctrl+C to gracefully shut down the server" << std::endl; server.bind(8080) .with_signals(); // Enable signal handling for graceful shutdown server.start(); // Wait for shutdown signal (blocks until server stops) server.wait_for_signal(); std::cout << "Server shut down successfully" << std::endl; return 0; } ``` -------------------------------- ### Basic HTTP GET Request Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/http-client.md Demonstrates how to make a simple GET request to a URL using the Glaze HTTP client. Includes error handling and accessing response details like status code, body, and headers. ```cpp #include "glaze/net/http_client.hpp" int main() { glz::http_client client; auto response = client.get("https://example.com"); if (response) { std::cout << "Status: " << response->status_code << std::endl; std::cout << "Body: " << response->response_body << std::endl; // Access response headers for (const auto& [name, value] : response->response_headers) { std::cout << name << ": " << value << std::endl; } } else { std::cerr << "Error: " << response.error().message() << std::endl; } return 0; } ``` -------------------------------- ### HTTPS Server Setup Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/http-server.md Shows how to create an HTTPS server, load SSL certificates, set verification modes, define a secure route, and bind the server to a port. ```cpp #include "glaze/net/http_server.hpp" // Create HTTPS server (template parameter enables TLS) glz::https_server server; // or glz::http_server // Load SSL certificates server.load_certificate("cert.pem", "key.pem"); server.set_ssl_verify_mode(0); // No client verification server.get("/secure", [](const glz::request& req, glz::response& res) { res.json({{"secure", true}, {"message", "This is HTTPS!"}}); }); server.bind(8443); server.start(); ``` -------------------------------- ### YAML Document Markers Source: https://github.com/stephenberry/glaze/blob/main/docs/yaml.md Example demonstrating the use of YAML document start (---) and end (...) markers. The start marker is optional and skipped during parsing, while the end marker signifies the end of a document. ```yaml --- # Document start marker (optional) key: value ... # Document end marker (optional) ``` -------------------------------- ### HTTPS Server Setup Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/http-server.md Illustrates how to create an HTTPS server, load SSL certificates, configure SSL verification, define a secure route, and bind the server to a port. ```APIDOC ## HTTPS Server Setup ### Description This example demonstrates setting up an HTTPS server. It involves creating an `https_server` instance, loading certificate and key files, optionally setting SSL verification modes, defining a route that responds with JSON, and binding the server to a specified port. ### Method `glz::https_server` ### Endpoint `/secure` (GET) ### Parameters #### Request Body (Not applicable for this GET route) ### Response #### Success Response (200) - **secure** (boolean) - Indicates if the connection is secure. - **message** (string) - A message from the server. ### Code Example ```cpp #include "glaze/net/http_server.hpp" // Create HTTPS server (template parameter enables TLS) glz::https_server server; // or glz::http_server // Load SSL certificates server.load_certificate("cert.pem", "key.pem"); server.set_ssl_verify_mode(0); // No client verification server.get("/secure", [](const glz::request& req, glz::response& res) { res.json({{"secure", true}, {"message", "This is HTTPS!"}}); }); server.bind(8443); server.start(); ``` ``` -------------------------------- ### Basic WebSocket Client Usage Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/websocket-client.md Demonstrates initializing a client, setting up event handlers, connecting to a server, and running the event loop. ```cpp #include "glaze/net/websocket_client.hpp" int main() { glz::websocket_client client; // Setup event handlers client.on_open([]() { std::cout << "Connected to WebSocket server!" << std::endl; }); client.on_message([](std::string_view message, glz::ws_opcode opcode) { if (opcode == glz::ws_opcode::text) { std::cout << "Received: " << message << std::endl; } }); client.on_close([](glz::ws_close_code code, std::string_view reason) { std::cout << "Connection closed with code: " << static_cast(code); if (!reason.empty()) { std::cout << ", reason: " << reason; } std::cout << std::endl; }); client.on_error([](std::error_code ec) { std::cerr << "Error: " << ec.message() << std::endl; }); // Connect to WebSocket server client.connect("ws://localhost:8080/ws"); // Run the io_context (blocks until connection is closed) client.run(); return 0; } ``` -------------------------------- ### Resetting Parse Position in Lazy BEVE Source: https://github.com/stephenberry/glaze/blob/main/docs/lazy-beve.md Shows how to reset the parser's position to the beginning of the document. Call `reset_parse_pos()` when you need to re-scan from the start, for example, after performing wrap-around accesses. ```cpp doc.reset_parse_pos(); // Next access starts from beginning ``` -------------------------------- ### Complete CMake Example with Bundled Glaze and Standalone Asio Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/asio-setup.md A full CMakeLists.txt demonstrating how to fetch Glaze and standalone Asio using FetchContent, then link them to your executable. Includes MSVC specific preprocessor option. ```cmake cmake_minimum_required(VERSION 3.20) project(MyNetworkingApp LANGUAGES CXX) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) include(FetchContent) # Fetch Glaze FetchContent_Declare( glaze GIT_REPOSITORY https://github.com/stephenberry/glaze.git GIT_TAG main GIT_SHALLOW TRUE ) FetchContent_MakeAvailable(glaze) # Fetch standalone ASIO FetchContent_Declare( asio GIT_REPOSITORY https://github.com/chriskohlhoff/asio.git GIT_TAG asio-1-36-0 GIT_SHALLOW TRUE ) FetchContent_MakeAvailable(asio) add_executable(myapp main.cpp) target_link_libraries(myapp PRIVATE glaze::glaze) target_include_directories(myapp PRIVATE ${asio_SOURCE_DIR}/asio/include) # MSVC specific if(MSVC) target_compile_options(myapp PRIVATE /Zc:preprocessor) endif() ``` -------------------------------- ### Creating a WebSocket Client Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/websocket-client.md Shows how to instantiate the client with either a default or a shared ASIO io_context. ```cpp // Create with default io_context glz::websocket_client client; // Create with shared io_context auto io_ctx = std::make_shared(); glz::websocket_client client(io_ctx); ``` -------------------------------- ### Basic WebSocket Server Setup Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/advanced-networking.md This snippet demonstrates how to create a basic WebSocket server, handle new connections, process incoming messages, and manage connection closures and errors. It's useful for general-purpose WebSocket communication. ```cpp #include "glaze/net/websocket_connection.hpp" // Create WebSocket server auto ws_server = std::make_shared(); // Handle new connections ws_server->on_open([](std::shared_ptr conn, const glz::request& req) { std::cout << "WebSocket connection opened from " << conn->remote_address() << std::endl; conn->send_text("Welcome to the WebSocket server!"); }); // Handle incoming messages ws_server->on_message([](std::shared_ptr conn, std::string_view message, glz::ws_opcode opcode) { if (opcode == glz::ws_opcode::text) { std::cout << "Received: " << message << std::endl; // Echo message back conn->send_text("Echo: " + std::string(message)); } }); // Handle connection close ws_server->on_close([](std::shared_ptr conn) { std::cout << "WebSocket connection closed" << std::endl; }); // Handle errors ws_server->on_error([](std::shared_ptr conn, std::error_code ec) { std::cerr << "WebSocket error: " << ec.message() << std::endl; }); // Mount WebSocket on HTTP server glz::http_server server; server.websocket("/ws", ws_server); server.bind(8080).with_signals(); server.start(); server.wait_for_signal(); ``` -------------------------------- ### Serialize C++ Struct to JSON String Source: https://github.com/stephenberry/glaze/blob/main/README.md Serialize a C++ struct into a JSON formatted string. This example shows two common patterns: directly getting the value or handling potential errors. ```c++ my_struct s{}; std::string buffer = glz::write_json(s).value_or("error"); ``` ```c++ my_struct s{}; std::string buffer{}; auto ec = glz::write_json(s, buffer); if (ec) { // handle error } ``` -------------------------------- ### Handling Buffer Overflow with std::array Source: https://github.com/stephenberry/glaze/blob/main/docs/writing.md Provides an example of handling `glz::error_code::buffer_overflow` when writing to a fixed-size buffer. It explains that `ec.count` is a lower bound and how to get the full required size. ```cpp std::array small_buffer; auto ec = glz::write_json(large_object, small_buffer); if (ec.ec == glz::error_code::buffer_overflow) { // ec.count contains bytes written before overflow // This is a LOWER BOUND on required size (not total required) // The partial content is NOT valid JSON - do not parse or transmit // Useful only for debugging: std::string_view partial(small_buffer.data(), ec.count); log_debug("Overflow after {} bytes: {}", ec.count, partial); // To get actual required size, use the string-returning overload: auto full = glz::write_json(large_object); if (full) { size_t required = full->size(); } } ``` -------------------------------- ### HTTPS Server Setup Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/tls-support.md Demonstrates how to create and configure a basic HTTPS server using Glaze, including loading certificates and defining routes. ```APIDOC ## POST /api/users ### Description Creates a new user in the system. ### Method POST ### Endpoint /api/users ### Parameters #### Request Body - **username** (string) - Required - The desired username for the new user. - **email** (string) - Required - The email address of the new user. - **password** (string) - Required - The password for the new user. ### Request Example ```json { "username": "johndoe", "email": "john.doe@example.com", "password": "securepassword123" } ``` ### Response #### Success Response (201) - **id** (string) - The unique identifier for the newly created user. - **username** (string) - The username of the created user. - **email** (string) - The email address of the created user. #### Response Example ```json { "id": "a1b2c3d4-e5f6-7890-1234-567890abcdef", "username": "johndoe", "email": "john.doe@example.com" } ``` ``` -------------------------------- ### Create a Basic HTTPS Server Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/tls-support.md Instantiate an HTTPS server using the `https_server` alias, load SSL certificate and key, define a route, and start the server on a specified port. ```cpp #include "glaze/net/http_server.hpp" int main() { // Create HTTPS server using alias glz::https_server server; // Load SSL certificate and private key server.load_certificate("path/to/cert.pem", "path/to/private_key.pem"); // Configure routes server.get("/", [](const glz::request& req, glz::response& res) { res.body("Hello, HTTPS World!"); }); // Start server on port 8443 server.bind(8443).start(); return 0; } ``` -------------------------------- ### Setup Asio Backend Source: https://github.com/stephenberry/glaze/blob/main/tests/CMakeLists.txt Includes and sets up the Asio backend for networking tests. This ensures consistency between the library and its backends. ```cmake # Setup the Asio backend (Boost / standalone / bundled) used by networking tests. # Selection plus the GLZ_USE_BOOST_ASIO bridge live in cmake/glaze-asio.cmake, the # single source of truth shared with the benchmarks, so glaze/ext/glaze_asio.hpp and # the backend CMake links can never disagree (issue #2599). Must run before # glz_test_common/glz_test_exceptions, which link glaze::asio. # # Distro maintainers can set -Dglaze_USE_BUNDLED_ASIO=OFF to require system packages. list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../cmake") include(glaze-asio) glaze_setup_asio() ``` -------------------------------- ### Basic HTTP Server Implementation Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/http-rest-support.md Initializes a basic HTTP server with a GET route and binds it to a specific address and port. ```cpp #include "glaze/net/http_server.hpp" #include int main() { glz::http_server server; server.get("/hello", [](const glz::request& /*req*/, glz::response& res) { res.body("Hello, World!"); }); // Note: start() is non-blocking; block the main thread until shutdown server.bind("127.0.0.1", 8080) .with_signals(); // enable Ctrl+C (SIGINT) handling std::cout << "Server running on http://127.0.0.1:8080\n"; std::cout << "Press Ctrl+C to stop\n"; server.start(); server.wait_for_signal(); return 0; } ``` -------------------------------- ### Complex Template Example Source: https://github.com/stephenberry/glaze/blob/main/docs/stencil-mustache.md A comprehensive template example demonstrating mixed features. ```cpp std::string_view blog_template = R"( {{title}}

{{title}}

{{description}}

{{{raw_html}}}
{{#has_items}}
    {{#items}}
  • {{text}} {{#completed}}✓{{/completed}}
  • {{/items}}
{{/has_items}} )"; ``` -------------------------------- ### Initialize and Run Glaze Microservice Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/http-examples.md Configures the server from environment variables, sets up middleware for metrics and error handling, and mounts REST and health endpoints. ```cpp config.port = std::atoi(port_env); } if (const char* log_level = std::getenv("LOG_LEVEL")) { config.log_level = log_level; } if (const char* db_url = std::getenv("DATABASE_URL")) { config.database_url = db_url; } return config; } }; int main() { // Load configuration Config config = Config::load_from_env(); std::cout << "Starting Product Microservice v1.0.0" << std::endl; std::cout << "Port: " << config.port << std::endl; std::cout << "Log Level: " << config.log_level << std::endl; glz::http_server server; ProductService productService; MetricsData metrics; HealthChecker health_checker; // Add metrics middleware server.use(create_metrics_middleware(metrics)); // Error handling middleware server.use([&metrics](const glz::request& req, glz::response& res) { if (res.status_code >= 400) { metrics.error_count++; } }); // Create REST registry glz::registry registry; registry.on(productService); // Mount API endpoints server.mount("/api/v1", registry.endpoints); // Health endpoints server.get("/health", [&health_checker, &metrics](const glz::request&, glz::response& res) { auto health = health_checker.get_health_status(metrics); if (health.status == "healthy") { res.status(200); } else { res.status(503); } res.json(health); }); server.get("/health/ready", [](const glz::request&, glz::response& res) { // Readiness check - are we ready to receive traffic? res.json({{"status", "ready"}}); }); server.get("/health/live", [](const glz::request&, glz::response& res) { // Liveness check - is the service still running? res.json({{"status", "alive"}}); }); // Metrics endpoint server.get("/metrics", [&metrics](const glz::request&, glz::response& res) { res.content_type("text/plain").body( "# HELP http_requests_total Total HTTP requests\n" "# TYPE http_requests_total counter\n" "http_requests_total " + std::to_string(metrics.total_requests.load()) + "\n" "# HELP http_errors_total Total HTTP errors\n" "# TYPE http_errors_total counter\n" "http_errors_total " + std::to_string(metrics.error_count.load()) + "\n" ); }); // Info endpoint server.get("/info", [&config](const glz::request&, glz::response& res) { res.json({ {"service", "product-service"}, {"version", "1.0.0"}, {"environment", config.log_level}, {"build_time", __DATE__ " " __TIME__} }); }); // Enable CORS if configured if (config.enable_cors) { server.enable_cors(); } try { std::cout << "Product Microservice listening on port " << config.port << std::endl; std::cout << "Health check: http://localhost:" << config.port << "/health" << std::endl; std::cout << "API docs: http://localhost:" << config.port << "/api/v1" << std::endl; std::cout << "Press Ctrl+C to gracefully shut down the server" << std::endl; server.bind(config.port) .with_signals(); // Enable built-in signal handling for graceful shutdown server.start(); // Wait for shutdown signal (blocks until server stops) server.wait_for_signal(); std::cout << "Product Microservice shut down successfully" << std::endl; } catch (const std::exception& e) { std::cerr << "Failed to start server: " << e.what() << std::endl; return 1; } return 0; } ``` -------------------------------- ### Define Struct for CSV Source: https://github.com/stephenberry/glaze/blob/main/docs/csv.md Example struct definition used for CSV serialization examples. ```c++ struct my_struct { std::vector num1{}; std::deque num2{}; std::vector maybe{}; std::vector> v3s{}; }; ``` -------------------------------- ### Build HTTP Response with Status, Headers, and Body Source: https://github.com/stephenberry/glaze/blob/main/docs/networking/http-server.md Demonstrates setting status codes, headers, content type, and the response body. Shows method chaining for concise response building. ```cpp server.get("/api/data", [](const glz::request& req, glz::response& res) { // Set status code res.status(200); // Set headers res.header("X-Custom-Header", "value"); res.content_type("application/json"); // Set body res.body("{\"message\": \"Hello\"}"); // Method chaining res.status(201) .header("Location", "/api/data/123") .json({{"id", 123}, {"created", true}}); }); ```