Code/Comments tweak to Networking scenario (#488)

This commit is contained in:
Peter Turcan
2025-08-07 10:23:27 -07:00
committed by GitHub
parent 250ee60704
commit ee7eb57dad

View File

@@ -545,35 +545,63 @@ namespace http = beast::http;
namespace json = boost::json;
using tcp = asio::ip::tcp;
// Function to handle incoming HTTP requests
void handle_request(http::request<http::string_body> req, http::response<http::string_body>& res) {
// Function to handle incoming HTTP requests and produce appropriate responses
void handle_request(
http::request<http::string_body> req, // Incoming HTTP request
http::response<http::string_body>& res // Outgoing HTTP response (to be filled in)
) {
// JSON object to hold the response body
json::object response_json;
// Log request information to the console for debugging
std::cout << "Method: " << req.method() << "...\n";
std::cout << "Target: " << req.target() << "...\n";
std::cout << "Body: " << req.body() << "...\n\n";
// Route: GET /status — return a simple status message
if (req.method() == http::verb::get && req.target() == "/status") {
response_json["status"] = "Server is running!";
}
// Route: POST /greet — expects JSON input and returns a personalized greeting
else if (req.method() == http::verb::post && req.target() == "/greet") {
try {
// Parse the incoming request body as JSON
json::value parsed_body = json::parse(req.body());
// Extract the "name" field from the JSON object
std::string name = parsed_body.as_object()["name"].as_string().c_str();
// Compose a greeting message
response_json["message"] = "Hello, " + name + "!";
}
catch (...) {
// If parsing fails or "name" field is missing, return an error
response_json["error"] = "Invalid JSON format.";
}
}
// Handle all other unknown endpoints or unsupported methods
else {
response_json["error"] = "Unknown endpoint.";
}
// Set the response status to 200 OK
res.result(http::status::ok);
// Specify the content type as JSON
res.set(http::field::content_type, "application/json");
// Serialize the JSON object and assign it to the response body
res.body() = json::serialize(response_json);
// Finalize the response by preparing content-length and other headers
res.prepare_payload();
}
// HTTP Server function
void run_server(asio::io_context& ioc, unsigned short port) {
tcp::acceptor acceptor(ioc, tcp::endpoint(tcp::v4(), port));
@@ -623,37 +651,62 @@ namespace http = beast::http;
namespace json = boost::json;
using tcp = asio::ip::tcp;
// Function to send an HTTP request
std::string send_request(const std::string& host, const std::string& port, http::verb method, const std::string& target, const std::string& body = "") {
// Function to send a basic HTTP request using Boost.Beast (synchronous, plain TCP)
std::string send_request(
const std::string& host, // e.g., "api.example.com"
const std::string& port, // e.g., "80" or "443" (for HTTPS you'd need SSL setup)
http::verb method, // HTTP method, e.g., http::verb::post or http::verb::get
const std::string& target, // The path/resource being requested, e.g., "/v1/data"
const std::string& body = "" // Optional request body (for POST/PUT)
) {
try {
// Create an I/O context required for all I/O operations
asio::io_context ioc;
// Create a resolver to turn the host name into a TCP endpoint
tcp::resolver resolver(ioc);
// Create the TCP stream for connecting and communicating
beast::tcp_stream stream(ioc);
// Resolve the host and port into a list of endpoints
auto const results = resolver.resolve(host, port);
// Establish a connection to one of the resolved endpoints
stream.connect(results);
http::request<http::string_body> req{ method, target, 11 };
req.set(http::field::host, host);
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
req.set(http::field::content_type, "application/json");
req.body() = body;
req.prepare_payload();
if (!body.empty()) req.body() = body;
// Build the HTTP request message
http::request<http::string_body> req{ method, target, 11 }; // HTTP/1.1
req.set(http::field::host, host); // Required: Host header
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); // Optional: Identifies the client
req.set(http::field::content_type, "application/json"); // Optional: for JSON bodies
req.body() = body; // Set the request body (if any)
req.prepare_payload(); // Sets Content-Length and finalizes headers
// Send the HTTP request to the remote host
http::write(stream, req);
// Buffer for receiving data
beast::flat_buffer buffer;
// Container for the HTTP response
http::response<http::string_body> res;
// Receive the response
http::read(stream, buffer, res);
// Return only the response body as a string
return res.body();
}
catch (std::exception& e) {
// Return the exception message prefixed with "Client error:"
return std::string("Client error: ") + e.what();
}
}
int main() {
std::string host = "127.0.0.1";
std::string port = "8080";