### Full uWebSockets Application Example in C++ Source: https://github.com/unetworking/uwebsockets/blob/master/misc/READMORE.md A complete example demonstrating how to set up a basic uWebSockets server. It defines a GET route that responds with 'Hello World!', starts listening on port 9001, and then runs the event loop. The code includes error handling for the listening process. ```c++ int main() { uWS::App().get("/*", [](auto *res, auto *req) { res->end("Hello World!"); }).listen(9001, [](auto *listenSocket) { if (listenSocket) { std::cout << "Listening for connections..." << std::endl; } }).run(); std::cout << "Shoot! We failed to listen and the App fell through, exiting now!" << std::endl; } ``` -------------------------------- ### Defining Routes (GET, POST, PUT, etc.) Source: https://github.com/unetworking/uwebsockets/blob/master/misc/READMORE.md This section covers how to attach behavior to URL routes using HTTP methods and pattern matching. Examples demonstrate the basic signature for defining routes. ```APIDOC ## GET, POST, PUT, [...] and any routes ### Description Attach behavior to URL routes by pairing a lambda function with an HTTP method and a URL matching pattern. ### Method GET, POST, PUT, DELETE, OPTIONS, PATCH, HEAD, ANY (matches any HTTP method) ### Endpoint `/your/url/pattern` ### Parameters #### Path Parameters None explicitly defined in the example, but patterns can include parameters like `/candy/:kind`. #### Query Parameters Not specified in the basic route definition. #### Request Body Not specified in the basic route definition. ### Request Example ```c++ uWS::App().get("/hello", [](auto *res, auto *req) { res->end("Hello World!"); }); ``` ### Response #### Success Response (200) Depends on the implementation within the lambda function. `res->end("Hello World!")` sends a simple string. #### Response Example ```json { "example": "Hello World!" } ``` ### Notes - `req` (uWS::HttpRequest *) is stack-allocated and dies with the return. Do not store it. - `res` (uWS::HttpResponse *) is alive until `onAborted` emits or `res->end()` or `res->tryEnd()` is called. - Data captured in `res` follows RAII and is move-only, suitable for moving string buffers or other resources. - The `any` route matches any HTTP method but has lower priority than specific method routes if specificity is otherwise equal. ``` -------------------------------- ### Implement WebSocket Pub/Sub with SSL in C++ Source: https://context7.com/unetworking/uwebsockets/llms.txt This example demonstrates how to set up a WebSocket server with SSL enabled and utilize the built-in topic-based publish-subscribe mechanism. It shows how clients can subscribe to topics, publish messages, and how messages can be broadcasted from outside the WebSocket handlers. ```cpp #include "App.h" #include int main() { struct PerSocketData {}; uWS::SSLApp app = uWS::SSLApp({ .key_file_name = "misc/key.pem", .cert_file_name = "misc/cert.pem", .passphrase = "1234" }).ws("/*", { .compression = uWS::SHARED_COMPRESSOR, .maxPayloadLength = 16 * 1024 * 1024, .idleTimeout = 16, .maxBackpressure = 1 * 1024 * 1024, .open = [](auto *ws) { // Subscribe to topics on connect ws->subscribe("broadcast"); ws->subscribe("chat/general"); ws->subscribe("user/123"); }, .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) { // Publish to a topic (sender excluded if subscribed) ws->publish("chat/general", message, opCode); }, .close = [](auto *ws, int code, std::string_view message) { // Subscriptions automatically cleaned up on close } }).listen(9001, [](auto *listen_socket) { if (listen_socket) { std::cout << "Listening on port 9001" << std::endl; } }); // Broadcast from outside WebSocket handlers using App.publish struct us_loop_t *loop = (struct us_loop_t *) uWS::Loop::get(); struct us_timer_t *timer = us_create_timer(loop, 0, 0); // Store app pointer for timer callback static uWS::SSLApp *globalApp = &app; us_timer_set(timer, [](struct us_timer_t *t) { struct timespec ts; timespec_get(&ts, TIME_UTC); int64_t millis = ts.tv_sec * 1000 + ts.tv_nsec / 1000000; // Publish timestamp to all "broadcast" subscribers globalApp->publish("broadcast", std::string_view((char *)&millis, sizeof(millis)), uWS::OpCode::BINARY, false); }, 8, 8); // Every 8ms app.run(); } ``` -------------------------------- ### Handle URL Parameters and Wildcards in Routes Source: https://context7.com/unetworking/uwebsockets/llms.txt Shows how to define routes with URL parameters (e.g., `:name`) and wildcards (e.g., `*`). It demonstrates retrieving parameter values by index or name using `req->getParameter()` and explains the route matching specificity. The example uses an SSL-enabled app listening on port 3000. ```cpp #include "App.h" int main() { uWS::SSLApp({ .key_file_name = "misc/key.pem", .cert_file_name = "misc/cert.pem", .passphrase = "1234" }).get("/:first/static/:second", [](auto *res, auto *req) { // Access URL parameters by index // For URL /hello/static/world: // getParameter(0) returns "hello" // getParameter(1) returns "world" res->write("

first is: "); res->write(req->getParameter("first")); res->write("

"); res->write("

second is: "); res->write(req->getParameter("second")); res->end("

"); }).listen(3000, [](auto *listen_socket) { if (listen_socket) { std::cout << "Listening on port 3000" << std::endl; } }).run(); } ``` -------------------------------- ### HTTP Route Methods Source: https://context7.com/unetworking/uwebsockets/llms.txt Explains how to define routes for different HTTP methods like GET, POST, PUT, DELETE, etc., using the uWS::App builder pattern. It also covers the `any()` method for catching all unmatched routes. ```APIDOC ## GET /users ### Description Retrieves a list of all users. The response is formatted as a JSON object containing a list of usernames. ### Method GET ### Endpoint /users ### Parameters #### Query Parameters - None ### Response #### Success Response (200) - **users** (array of strings) - A list of usernames. #### Response Example ```json { "users": ["alice", "bob"] } ``` ## POST /users ### Description Creates a new user. This endpoint handles incoming data in the request body and processes it using the `onData` callback. It also includes an `onAborted` callback for handling request abortions. ### Method POST ### Endpoint /users ### Parameters #### Query Parameters - None #### Request Body - **data** (string) - Required - The data for the new user, typically JSON. ### Response #### Success Response (200) - **message** (string) - A confirmation message indicating the user was created or the request was processed. #### Response Example ```json { "message": "User created" } ``` ## DELETE /users/:id ### Description Deletes a user specified by their ID. The user ID is extracted from the URL path parameters. ### Method DELETE ### Endpoint /users/:id ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the user to be deleted. ### Response #### Success Response (200) - **message** (string) - A confirmation message indicating the user was deleted, including the deleted user's ID. #### Response Example ```json { "message": "Deleted user: 123" } ``` ## ANY /* ### Description A catch-all route that handles any HTTP method and path not explicitly defined by other routes. It returns a '404 Not Found' status. ### Method ANY (GET, POST, PUT, DELETE, etc.) ### Endpoint /* ### Parameters #### Query Parameters - None ### Response #### Success Response (404) - **message** (string) - Indicates that the requested resource was not found. #### Response Example ```json { "message": "Not Found" } ``` ``` -------------------------------- ### Start Listening for Connections in C++ Source: https://github.com/unetworking/uwebsockets/blob/master/misc/READMORE.md Initiates a uWebSockets application to listen for incoming network connections on a specified port. It takes a port number and a callback function that is executed once the listening socket is ready or if an error occurs. The callback receives a listen socket object. ```c++ App.listen(port, [](auto *listenSocket) { /* listenSocket is either nullptr or us_listen_socket */ }) ``` -------------------------------- ### Define HTTP Route Methods with uWS::App Source: https://context7.com/unetworking/uwebsockets/llms.txt Illustrates how to define various HTTP route handlers using different HTTP methods like GET, POST, DELETE, and a catch-all ANY route. It shows how to set response headers, handle POST data using onData, and manage request abortions. The server listens on port 3000. ```cpp #include "App.h" int main() { uWS::App() .get("/users", [](auto *res, auto *req) { res->writeHeader("Content-Type", "application/json"); res->end(R"({\"users\": [\"alice\", \"bob\"]})"); }) .post("/users", [](auto *res, auto *req) { // Handle POST data with onData callback res->onData([res](std::string_view data, bool last) { if (last) { res->end("User created"); } }); res->onAborted([]() { std::cout << "Request aborted" << std::endl; }); }) .del("/users/:id", [](auto *res, auto *req) { auto userId = req->getParameter(0); res->end("Deleted user: " + std::string(userId)); }) .any("/*", [](auto *res, auto *req) { // Catch-all for unmatched routes res->writeStatus("404 Not Found"); res->end("Not Found"); }) .listen(3000, [](auto *token) { if (token) std::cout << "Listening on port 3000" << std::endl; }).run(); } ``` -------------------------------- ### Multi-threaded Server with LocalCluster in C++ Source: https://context7.com/unetworking/uwebsockets/llms.txt Demonstrates scaling a uWebSockets server across CPU cores using `LocalCluster`. Each thread gets its own event loop and shares the listen port. This approach is suitable for CPU-bound tasks. ```cpp #include "App.h" #include "LocalCluster.h" int main() { // LocalCluster spawns threads automatically based on CPU cores uWS::LocalCluster({ .key_file_name = "misc/key.pem", .cert_file_name = "misc/cert.pem", .passphrase = "1234" }, [](uWS::SSLApp &app) { // This lambda runs in each thread with its own App instance app.get("/*", [](auto *res, auto *req) { res->end("Hello from thread!"); }).listen(3000, [](auto *listen_socket) { if (listen_socket) { std::cout << "Thread " << std::this_thread::get_id() << " listening on port " << us_socket_local_port(true, (struct us_socket_t *) listen_socket) << std::endl; } }); }); // LocalCluster blocks until all threads complete } ``` -------------------------------- ### Define GET Route in C++ Source: https://github.com/unetworking/uwebsockets/blob/master/misc/READMORE.md This snippet demonstrates how to define a GET route for a specific URL pattern ('/hello') and attach a lambda function to handle incoming requests. The lambda receives request and response objects, and 'res->end()' is used to send a response. Note that the 'req' object is stack-allocated and dies with the return, while 'res' remains accessible until a response is sent or an abort event occurs. ```c++ uWS::App().get("/hello", [](auto *res, auto *req) { res->end("Hello World!"); }); ``` -------------------------------- ### C++ Web Server with SSL, Routing, and WebSockets Source: https://github.com/unetworking/uwebsockets/blob/master/README.md This C++ code snippet demonstrates setting up a uWebSockets application with SSL enabled. It includes a GET route for '/hello/:name' that dynamically responds and a WebSocket handler for opening connections and echoing messages. The server listens on port 9001 and provides feedback on the listening status. ```c++ /* One app per thread; spawn as many as you have CPU-cores and let uWS share the listening port */ uWS::SSLApp({ /* These are the most common options, fullchain and key. See uSockets for more options. */ .cert_file_name = "cert.pem", .key_file_name = "key.pem" }).get("/hello/:name", [](auto *res, auto *req) { /* You can efficiently stream huge files too */ res->writeStatus("200 OK") ->writeHeader("Content-Type", "text/html; charset=utf-8") ->write("

Hello ") ->write(req->getParameter("name")) ->end("!

"); }).ws("/*", { /* Just a few of the available handlers */ .open = [](auto *ws) { ws->subscribe("oh_interesting_subject"); }, .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) { ws->send(message, opCode); } }).listen(9001, [](auto *listenSocket) { if (listenSocket) { std::cout << "Listening on port " << 9001 << std::endl; } else { std::cout << "Failed to load certs or to bind to port" << std::endl; } }).run(); ``` -------------------------------- ### Run uWebSockets Event Loop in C++ Source: https://github.com/unetworking/uwebsockets/blob/master/misc/READMORE.md Starts the uWebSockets event loop, which blocks the calling thread until the loop naturally falls through. The loop continues as long as there is asynchronous work scheduled. It should be called only once. The application gracefully exits when all sockets are closed and no more work is pending. ```c++ App.run(); ``` -------------------------------- ### Creating a Basic HTTP Server Source: https://context7.com/unetworking/uwebsockets/llms.txt Demonstrates how to create a basic HTTP server using uWS::App or uWS::SSLApp. It shows how to configure SSL and set up a simple route handler for all requests. ```APIDOC ## POST /api/users ### Description This endpoint allows for the creation of new users. It expects user data in the request body and returns a confirmation message upon successful creation. ### Method POST ### Endpoint /api/users ### Parameters #### Query Parameters - None #### Request Body - **username** (string) - Required - The desired username for the new user. - **email** (string) - Required - The email address of the new user. ### Request Example ```json { "username": "johndoe", "email": "john.doe@example.com" } ``` ### Response #### Success Response (200) - **message** (string) - A confirmation message indicating the user was created successfully. #### Response Example ```json { "message": "User created successfully." } ``` ``` -------------------------------- ### Create Basic HTTP Server with uWS::SSLApp Source: https://context7.com/unetworking/uwebsockets/llms.txt Demonstrates how to create a basic HTTP server using uWS::SSLApp, enabling TLS encryption. It configures SSL certificates and defines a simple route handler for the root path. The server listens on port 3000 and runs the event loop. ```cpp #include "App.h" int main() { // Create an SSL-enabled app with certificate configuration uWS::SSLApp({ .key_file_name = "misc/key.pem", .cert_file_name = "misc/cert.pem", .passphrase = "1234" }).get("/*", [](auto *res, auto *req) { // res is HttpResponse*, req is HttpRequest* // req is only valid within this callback - do not store it res->end("Hello world!"); }).listen(3000, [](auto *listen_socket) { if (listen_socket) { std::cout << "Listening on port 3000" << std::endl; } }).run(); // .run() blocks until the event loop falls through std::cout << "Server stopped" << std::endl; } ``` -------------------------------- ### Create WebSocket Server with Handlers in C++ Source: https://context7.com/unetworking/uwebsockets/llms.txt This snippet demonstrates how to create a WebSocket server using uWS::App. It configures various event handlers for open, message, drain, ping, pong, and close events. It also shows how to define and use custom per-socket user data. ```cpp #include "App.h" int main() { // Define per-socket user data structure struct PerSocketData { std::string username; int messageCount = 0; }; uWS::App().ws("/*", { /* Settings */ .compression = uWS::SHARED_COMPRESSOR, .maxPayloadLength = 16 * 1024, .idleTimeout = 120, .maxBackpressure = 1 * 1024 * 1024, .closeOnBackpressureLimit = false, .resetIdleTimeoutOnSend = false, .sendPingsAutomatically = true, /* Handlers */ .open = [](auto *ws) { // Initialize user data PerSocketData *userData = ws->getUserData(); userData->username = "anonymous"; std::cout << "WebSocket connected" << std::endl; }, .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) { // Echo the message back PerSocketData *userData = ws->getUserData(); userData->messageCount++; // opCode is TEXT or BINARY ws->send(message, opCode); }, .drain = [](auto *ws) { // Called when backpressure drains std::cout << "Buffered: " << ws->getBufferedAmount() << std::endl; }, .ping = [](auto *ws, std::string_view message) { // Pings are handled automatically }, .pong = [](auto *ws, std::string_view message) { // Received pong response }, .close = [](auto *ws, int code, std::string_view message) { // WebSocket closed - userData still valid here std::cout << "Closed with code " << code << std::endl; } }).listen(9001, [](auto *listen_socket) { if (listen_socket) { std::cout << "WebSocket server listening on port 9001" << std::endl; } }).run(); } ``` -------------------------------- ### URL Parameter Routes Source: https://context7.com/unetworking/uwebsockets/llms.txt Illustrates how to define routes with URL parameters (e.g., `:name`) and wildcards (e.g., `*`). It explains how to access these parameters using `req->getParameter()` and the route matching specificity. ```APIDOC ## GET /:first/static/:second ### Description This endpoint demonstrates the use of URL parameters. It captures values from the URL path and displays them in the response. Parameters are accessed by name or index. ### Method GET ### Endpoint /:first/static/:second ### Parameters #### Path Parameters - **first** (string) - Required - The value captured by the `:first` parameter in the URL. - **second** (string) - Required - The value captured by the `:second` parameter in the URL. ### Response #### Success Response (200) - **message** (string) - An HTML string displaying the captured parameter values. #### Response Example ```html

first is: hello

second is: world

``` ``` -------------------------------- ### Implementing Middleware-like Functionality Source: https://github.com/unetworking/uwebsockets/blob/master/misc/READMORE.md Discusses how to achieve middleware patterns using higher-order functions and functional programming, as uWebSockets does not have built-in middleware support. ```APIDOC ## Middlewares ### Description uWebSockets does not provide built-in middleware support in the router. However, similar functionality can be achieved using higher-order functions and functional programming techniques. ### Approach - **Regular Functions**: Treat middleware as regular functions that can be passed to other functions. - **Function Chaining**: Construct chains of behavior by passing functions as arguments. - **RAII and Move-Only Captures**: Utilize RAII principles and move-only captures in lambdas to manage resources and data across asynchronous operations. ### Notes - The `HttpRequest` object is stack-allocated and only valid within a single callback invocation, making traditional middleware difficult. - The library aims to provide a flexible server implementation, encouraging users to build custom logic like middleware using standard programming paradigms. - Examples of this pattern can often be found in community discussions or related projects. ``` -------------------------------- ### Write HTTP Responses with HttpResponse API in C++ Source: https://context7.com/unetworking/uwebsockets/llms.txt Demonstrates how to use the HttpResponse API in C++ to write HTTP responses. This includes setting status codes, headers, and sending response bodies. It covers both immediate responses and streaming responses using chunked transfer encoding, as well as handling large data with backpressure. ```cpp #include "App.h" int main() { uWS::App().get("/api/data", [](auto *res, auto *req) { // Write status (defaults to 200 OK if not called) res->writeStatus("200 OK"); // Write headers res->writeHeader("Content-Type", "application/json"); res->writeHeader("X-Custom-Header", "value"); // End with body (calculates Content-Length automatically) res->end(R"({\"status\": \"success\"})"); }) .get("/stream", [](auto *res, auto *req) { // Streaming response using chunked transfer encoding // write() enables chunked mode, returns false if backpressure builds res->writeStatus("200 OK"); res->writeHeader("Content-Type", "text/plain"); if (res->write("First chunk... ")) { res->write("Second chunk... "); } res->end("Final chunk"); // Ends chunked response }) .get("/large-file", [](auto *res, auto *req) { // For large data, use tryEnd to handle backpressure size_t totalSize = 1000000; std::string chunk(16384, 'x'); res->onWritable([res, chunk, totalSize](uintmax_t offset) { auto [ok, done] = res->tryEnd(chunk, totalSize); return ok; // Return true to keep onWritable active }); res->onAborted([]() { std::cout << "Download aborted" << std::endl; }); }) .listen(3000, [](auto *token) { if (token) std::cout << "Listening" << std::endl; }).run(); } ``` -------------------------------- ### Handling POST Data in C++ Source: https://context7.com/unetworking/uwebsockets/llms.txt Demonstrates how to read request body data for POST requests using the `onData` callback. Data is received in chunks, and the `last` parameter indicates the final chunk. ```cpp #include "App.h" int main() { uWS::App().post("/upload", [](auto *res, auto *req) { // Create a buffer to accumulate data (using mutable lambda capture) std::string buffer; res->onData([res, buffer = std::move(buffer)](std::string_view data, bool last) mutable { buffer.append(data); if (last) { // All data received std::cout << "Received " << buffer.length() << " bytes" << std::endl; res->cork([res, &buffer]() { res->writeHeader("Content-Type", "application/json"); res->end(R"({\"received\": )" + std::to_string(buffer.length()) + "}"); }); } }); res->onAborted([]() { std::cout << "Upload aborted" << std::endl; }); }) .listen(3000, [](auto *token) { if (token) std::cout << "Listening on 3000" << std::endl; }).run(); } // Test with curl: // curl -X POST -d "Hello World" http://localhost:3000/upload // curl -X POST -H "Content-Type: application/json" -d '{"key":"value"}' http://localhost:3000/upload ``` -------------------------------- ### Async WebSocket Upgrade with Auth in C++ Source: https://context7.com/unetworking/uwebsockets/llms.txt Handles WebSocket upgrades asynchronously, allowing for authentication or database lookups before accepting the connection. It uses a timer to simulate an asynchronous operation and corks the response to complete the upgrade efficiently. Dependencies include the uWebSockets library. ```cpp #include "App.h" int main() { struct PerSocketData { int userId; std::string token; }; uWS::SSLApp({ .key_file_name = "misc/key.pem", .cert_file_name = "misc/cert.pem", .passphrase = "1234" }).ws("/*", { .compression = uWS::SHARED_COMPRESSOR, .maxPayloadLength = 16 * 1024, .idleTimeout = 10, .upgrade = [](auto *res, auto *req, auto *context) { // IMPORTANT: req is only valid in this callback // Copy any needed data immediately struct UpgradeData { std::string secWebSocketKey; std::string secWebSocketProtocol; std::string secWebSocketExtensions; struct us_socket_context_t *context; decltype(res) httpRes; bool aborted = false; std::string authToken; } *upgradeData = new UpgradeData { std::string(req->getHeader("sec-websocket-key")), std::string(req->getHeader("sec-websocket-protocol")), std::string(req->getHeader("sec-websocket-extensions")), context, res, false, std::string(req->getHeader("authorization")) }; // Track if connection is aborted during async operation res->onAborted([upgradeData]() { upgradeData->aborted = true; }); // Simulate async auth check (e.g., database lookup) struct us_loop_t *loop = (struct us_loop_t *) uWS::Loop::get(); struct us_timer_t *timer = us_create_timer(loop, 0, sizeof(UpgradeData *)); memcpy(us_timer_ext(timer), &upgradeData, sizeof(UpgradeData *)); us_timer_set(timer, [](struct us_timer_t *t) { UpgradeData *data; memcpy(&data, us_timer_ext(t), sizeof(UpgradeData *)); if (!data->aborted) { // Auth succeeded - complete the upgrade data->httpRes->cork([data]() { data->httpRes->template upgrade({ .userId = 123, .token = data->authToken }, data->secWebSocketKey, data->secWebSocketProtocol, data->secWebSocketExtensions, data->context); }); } delete data; us_timer_close(t); }, 100, 0); // 100ms delay simulating auth }, .open = [](auto *ws) { auto *userData = ws->getUserData(); std::cout << "User " << userData->userId << " connected" << std::endl; }, .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) { ws->send(message, opCode); }, .close = [](auto *ws, int code, std::string_view message) {} }).listen(9001, [](auto *listen_socket) { if (listen_socket) { std::cout << "Listening on port 9001" << std::endl; } }).run(); } ``` -------------------------------- ### Performance Corking for HTTP and WebSockets in C++ Source: https://context7.com/unetworking/uwebsockets/llms.txt Demonstrates how to use the 'cork' feature in uWebSockets to batch multiple write operations into a single syscall, significantly improving performance for both HTTP responses and WebSocket messages. This reduces overhead by minimizing system calls and SSL operations. ```cpp #include "App.h" int main() { uWS::App().get("/efficient", [](auto *res, auto *req) { // Cork batches all writes into one send res->cork([res]() { res->writeStatus("200 OK"); res->writeHeader("Content-Type", "application/json"); res->writeHeader("Cache-Control", "no-cache"); res->writeHeader("X-Custom", "value"); res->end(R"({\"message\": \"All headers and body sent in one syscall\"})"); }); }) .ws("/*", { .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) { // WebSockets also benefit from corking ws->cork([ws, message, opCode]() { ws->send("First message", opCode); ws->send("Second message", opCode); ws->send(message, opCode); // All three sends batched into one write }); } }) .listen(3000, [](auto *token) { if (token) std::cout << "Listening" << std::endl; }).run(); } ``` -------------------------------- ### Define WebSocket Route with Handlers in C++ Source: https://github.com/unetworking/uwebsockets/blob/master/misc/READMORE.md Shows the structure for defining a WebSocket route in µWS using C++. It includes settings like compression and payload length, and outlines various event handlers such as upgrade, open, message, drain, ping, pong, and close. ```c++ uWS::App().ws("/*", { /* Settings */ .compression = uWS::SHARED_COMPRESSOR, .maxPayloadLength = 16 * 1024, .idleTimeout = 10, /* Handlers */ .upgrade = [](auto *res, auto *req, auto *context) { /* You may read from req only here, and COPY whatever you need into your PerSocketData. * See UpgradeSync and UpgradeAsync examples. */ }, .open = [](auto *ws) { }, .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) { ws->send(message, opCode); }, .drain = [](auto *ws) { /* Check getBufferedAmount here */ }, .ping = [](auto *ws, std::string_view message) { }, .pong = [](auto *ws, std::string_view message) { }, .close = [](auto *ws, int code, std::string_view message) { } }); ``` -------------------------------- ### Streaming Large Data with tryEnd in C++ Source: https://github.com/unetworking/uwebsockets/blob/master/misc/READMORE.md Illustrates the recommended approach for sending large amounts of data without causing backpressure spikes. Instead of using res.end() with a huge buffer, res.tryEnd() should be used to send data in parts. This method is typically used in conjunction with res.onWritable and res.onAborted callbacks for robust streaming. ```c++ // Example usage within a request handler: // res->tryEnd(chunk1, false); // Send first chunk, not the end // res->tryEnd(chunk2, false); // Send second chunk, not the end // res->tryEnd(finalChunk, true); // Send final chunk and end the response ``` -------------------------------- ### Scaling uWebSockets with Multiple Threads in C++ Source: https://github.com/unetworking/uwebsockets/blob/master/misc/READMORE.md Illustrates the concept of scaling a uWebSockets application by running multiple instances, each with its own event loop, potentially on separate threads. This approach promotes isolation and avoids shared data, similar to Node.js's multi-process model but applied per-thread in C++. It suggests that applications can listen on separate ports or share the same port (on Linux). ```c++ // Example concept for scaling: // std::thread t1([]() { // uWS::App()...listen(port1).run(); // }); // std::thread t2([]() { // uWS::App()...listen(port2).run(); // }); // t1.join(); // t2.join(); ``` -------------------------------- ### Access Request Information with HttpRequest API in C++ Source: https://context7.com/unetworking/uwebsockets/llms.txt Illustrates how to use the HttpRequest API in C++ to retrieve details about an incoming HTTP request. This includes accessing the HTTP method, URL, query string, and headers. The API provides efficient read-only access to this information within the route callback. ```cpp #include "App.h" int main() { uWS::App().get("/request-info", [](auto *res, auto *req) { // Get HTTP method std::string_view method = req->getMethod(); // "get", "post", etc. // Get URL path (without query string) std::string_view url = req->getUrl(); // "/request-info" // Get full URL including query string std::string_view fullUrl = req->getFullUrl(); // "/request-info?foo=bar" // Get query string std::string_view query = req->getQuery(); // "foo=bar" // Get specific query parameter std::string_view foo = req->getQuery("foo"); // "bar" // Get headers (lowercase keys) std::string_view host = req->getHeader("host"); std::string_view userAgent = req->getHeader("user-agent"); std::string_view contentType = req->getHeader("content-type"); // Iterate all headers for (auto [key, value] : *req) { std::cout << key << ": " << value << std::endl; } res->end("Request processed"); }) .listen(3000, [](auto *token) { if (token) std::cout << "Listening" << std::endl; }).run(); } ``` -------------------------------- ### Ensure Corking with Lambda Wrapper in C++ Source: https://github.com/unetworking/uwebsockets/blob/master/misc/READMORE.md Demonstrates how to manually ensure the corking mechanism is active for sending data, even in cases where automatic corking might not occur. This is crucial for performance, especially when sending multiple data chunks. ```c++ res->cork([res]() { res->end("This Http response will be properly corked and efficient in all cases"); }); ``` -------------------------------- ### WebSocket Compression Options in C++ Source: https://context7.com/unetworking/uwebsockets/llms.txt Configures WebSocket permessage-deflate compression with different memory and performance tradeoffs. Options include SHARED_COMPRESSOR, DEDICATED_COMPRESSOR_4KB, and DISABLED. ```cpp #include "App.h" int main() { struct PerSocketData {}; uWS::App().ws("/shared", { // SHARED_COMPRESSOR: No per-socket memory, each message compressed independently // Good for larger JSON messages .compression = uWS::SHARED_COMPRESSOR, .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) { ws->send(message, opCode, true); // true = compress } }) .ws("/dedicated-4k", { // DEDICATED_COMPRESSOR_4KB: 4KB per socket, sliding window compression // Better compression ratio for small messages .compression = uWS::DEDICATED_COMPRESSOR_4KB, .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) { ws->send(message, opCode, true); } }) .ws("/no-compression", { // DISABLED: No compression overhead, best for binary data .compression = uWS::DISABLED, .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) { ws->send(message, opCode, false); } }) .listen(9001, [](auto *token) { if (token) std::cout << "Listening on 9001" << std::endl; }).run(); } ``` -------------------------------- ### Route Pattern Matching Priority Source: https://github.com/unetworking/uwebsockets/blob/master/misc/READMORE.md Explains the order of specificity for route matching, from highest to lowest priority. ```APIDOC ## Pattern Matching Priority ### Description Routes are matched based on their specificity, not the order they are registered. More specific routes take precedence. ### Priority Order (Highest to Lowest) 1. **Static Routes**: Exact URL paths (e.g., `/hello/this/is/static`). 2. **Parameter Routes**: Paths with named parameters (e.g., `/candy/:kind`). The parameter value can be retrieved using `req.getParameter(index)`. 3. **Wildcard Routes**: Paths ending with a wildcard (e.g., `/hello/*`). ### Notes - This priority system allows for defining broad wildcard routes and then overriding them with more specific ones. - When two routes have equal specificity, an 'any' route (matching any method) will have lower priority than a route specifying a particular HTTP method (like GET). ``` -------------------------------- ### SNI (Server Name Indication) Support in C++ Source: https://context7.com/unetworking/uwebsockets/llms.txt Enables serving multiple TLS certificates from a single server based on the requested hostname. It allows defining specific certificates for different domains and handling requests for unknown hostnames. ```cpp #include "App.h" int main() { uWS::SSLApp({ // Default certificate .key_file_name = "default-key.pem", .cert_file_name = "default-cert.pem" }) // Add additional certificates for specific hostnames .addServerName("api.example.com", { .key_file_name = "api-key.pem", .cert_file_name = "api-cert.pem" }) .addServerName("www.example.com", { .key_file_name = "www-key.pem", .cert_file_name = "www-cert.pem" }) // Handle requests for unknown hostnames .missingServerName([](const char *hostname) { std::cout << "No certificate for: " << hostname << std::endl; }) // Define routes per domain .domain("api.example.com") .get("/*", [](auto *res, auto *req) { res->end("API response"); }) .domain("www.example.com") .get("/*", [](auto *res, auto *req) { res->end("Website response"); }) .listen(443, [](auto *token) { if (token) std::cout << "Listening on 443" << std::endl; }).run(); } ```