From 7db52b4b2e8f2bf3f98aac5f148b7c2fdd4cc52b Mon Sep 17 00:00:00 2001 From: hieudoanm Date: Mon, 10 Feb 2025 00:46:57 +0700 Subject: [PATCH] Update README --- README.md | 2 +- docs/README.md | 2 +- languages/cplusplus/Makefile | 5 ++ languages/cplusplus/README.md | 1 + languages/cplusplus/example.http | 1 + languages/cplusplus/main.cpp | 107 +++++++++++++++++++++++++++++++ 6 files changed, 116 insertions(+), 2 deletions(-) create mode 100644 languages/cplusplus/Makefile create mode 100644 languages/cplusplus/README.md create mode 100644 languages/cplusplus/example.http create mode 100644 languages/cplusplus/main.cpp diff --git a/README.md b/README.md index 1bb69ae..2fcfda9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Reverse Proxy -- C++ (In Progress) +- [C++](https://cplusplus.com/) - [Go](https://go.dev/) - [Node.js](https://nodejs.org/en) - [Python](https://python.org) diff --git a/docs/README.md b/docs/README.md index 1bb69ae..2fcfda9 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ # Reverse Proxy -- C++ (In Progress) +- [C++](https://cplusplus.com/) - [Go](https://go.dev/) - [Node.js](https://nodejs.org/en) - [Python](https://python.org) diff --git a/languages/cplusplus/Makefile b/languages/cplusplus/Makefile new file mode 100644 index 0000000..0764f29 --- /dev/null +++ b/languages/cplusplus/Makefile @@ -0,0 +1,5 @@ +build: + g++ main.cpp -o main + +start: + ./main diff --git a/languages/cplusplus/README.md b/languages/cplusplus/README.md new file mode 100644 index 0000000..63c3dff --- /dev/null +++ b/languages/cplusplus/README.md @@ -0,0 +1 @@ +# C++ diff --git a/languages/cplusplus/example.http b/languages/cplusplus/example.http new file mode 100644 index 0000000..8b40776 --- /dev/null +++ b/languages/cplusplus/example.http @@ -0,0 +1 @@ +GET http://localhost:8080/?target=http://jsonplaceholder.typicode.com/todos/1 diff --git a/languages/cplusplus/main.cpp b/languages/cplusplus/main.cpp new file mode 100644 index 0000000..2e4cebe --- /dev/null +++ b/languages/cplusplus/main.cpp @@ -0,0 +1,107 @@ +#include +#include +#include +#include + +namespace beast = boost::beast; +namespace http = beast::http; +namespace net = boost::asio; +using tcp = net::ip::tcp; + +// Extract target host and path from query +bool parse_target_url(const std::string& request, std::string& host, std::string& path) { + size_t pos = request.find("?target=http://"); + if (pos == std::string::npos) return false; + + std::string target = request.substr(pos + 9); + size_t path_start = target.find("/"); + if (path_start == std::string::npos) { + host = target; + path = "/"; + } else { + host = target.substr(0, path_start); + path = target.substr(path_start); + } + return true; +} + +// Forward HTTP request to the target server +std::string forward_request(const std::string& host, const std::string& path, net::io_context& ioc) { + try { + tcp::resolver resolver(ioc); + tcp::socket socket(ioc); + + // Resolve domain and connect + auto endpoints = resolver.resolve(host, "80"); + net::connect(socket, endpoints); + + // Create HTTP GET request + http::request req{http::verb::get, path, 11}; + req.set(http::field::host, host); + req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); + + // Send request + http::write(socket, req); + + // Receive response + beast::flat_buffer buffer; + http::response res; + http::read(socket, buffer, res); + + // Convert response body to string + std::ostringstream response_stream; + response_stream << res; + + return response_stream.str(); + } catch (std::exception& e) { + return "HTTP/1.1 502 Bad Gateway\r\n\r\nError: " + std::string(e.what()); + } +} + +// Handle client requests +void handle_client(tcp::socket client_socket) { + beast::flat_buffer buffer; + http::request req; + + try { + // Read HTTP request from client + http::read(client_socket, buffer, req); + std::string request_text = req.target().to_string(); + + // Extract target host & path from query + std::string host, path; + if (!parse_target_url(request_text, host, path)) { + std::string error_response = "HTTP/1.1 400 Bad Request\r\n\r\nMissing target URL"; + http::write(client_socket, http::response{http::status::bad_request, 11, error_response}); + return; + } + + // Forward request to target server + net::io_context ioc; + std::string response = forward_request(host, path, ioc); + + // Send response back to client + http::write(client_socket, http::response{http::status::ok, 11, response}); + } catch (std::exception& e) { + std::cerr << "Error: " << e.what() << "\n"; + } +} + +// Main function to start the proxy server +int main() { + try { + net::io_context ioc; + tcp::acceptor acceptor(ioc, {tcp::v4(), 8080}); + std::cout << "Reverse Proxy running on port 8080...\n"; + + while (true) { + tcp::socket socket(ioc); + acceptor.accept(socket); + std::thread(handle_client, std::move(socket)).detach(); + } + } catch (std::exception& e) { + std::cerr << "Error: " << e.what() << "\n"; + } + + return 0; +}