This commit is contained in:
parent
10e26e8a6c
commit
ede75f5565
3
.vscode/settings.json
vendored
Normal file
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"cmake.sourceDirectory": "/home/j/code/dropshell-build/ipdemo"
|
||||
}
|
18
CLAUDE.md
18
CLAUDE.md
@ -114,4 +114,20 @@ Applications can use:
|
||||
- MariaDB via connector at `/usr/local/mariadb-connector-c/`
|
||||
- SQLite3 at `/usr/local/sqlite3/`
|
||||
|
||||
All database libraries are statically linked into the final binary.
|
||||
All database libraries are statically linked into the final binary.
|
||||
|
||||
### HTTP Client Utilities
|
||||
|
||||
The ipdemo includes a blocking HTTP client utility (`src/http_utils.hpp`) that wraps Drogon's asynchronous HttpClient:
|
||||
|
||||
```cpp
|
||||
#include "http_utils.hpp"
|
||||
|
||||
// Make a blocking HTTP GET request
|
||||
auto response = http_get("example.com", "/api/endpoint", true, 10.0); // HTTPS with 10s timeout
|
||||
if (response.success && response.status_code == 200) {
|
||||
std::cout << response.body << std::endl;
|
||||
}
|
||||
```
|
||||
|
||||
This utility handles the threading complexity and provides a simple synchronous interface for HTTP requests.
|
@ -112,15 +112,9 @@ set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH}
|
||||
set(JSONCPP_INCLUDE_DIRS /usr/local/jsoncpp/include)
|
||||
set(JSONCPP_LIBRARIES /usr/local/jsoncpp/lib/libjsoncpp.a)
|
||||
|
||||
##########
|
||||
# If you include the drogon source code locally in your project, use this method to add drogon
|
||||
# add_subdirectory(external/drogon)
|
||||
# target_link_libraries(${PROJECT_NAME} PRIVATE drogon)
|
||||
##########
|
||||
find_package(Drogon CONFIG REQUIRED)
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Drogon::Drogon)
|
||||
|
||||
|
||||
# Additional PostgreSQL libraries needed for static linking
|
||||
set(POSTGRESQL_EXTRA_LIBS
|
||||
/usr/local/pgsql/lib/libpgcommon.a
|
||||
|
48
ipdemo/src/http_utils.cpp
Normal file
48
ipdemo/src/http_utils.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
#include "http_utils.hpp"
|
||||
|
||||
HttpResponse http_get(const std::string& url, const std::string& path, bool use_https, double timeout_seconds) {
|
||||
HttpResponse result{0, "", false};
|
||||
bool done = false;
|
||||
std::mutex mtx;
|
||||
std::condition_variable cv;
|
||||
|
||||
std::thread worker([&]() {
|
||||
trantor::EventLoop loop;
|
||||
|
||||
auto client = drogon::HttpClient::newHttpClient(
|
||||
(use_https ? "https://" : "http://") + url,
|
||||
&loop
|
||||
);
|
||||
|
||||
auto req = drogon::HttpRequest::newHttpRequest();
|
||||
req->setMethod(drogon::Get);
|
||||
req->setPath(path);
|
||||
|
||||
client->sendRequest(req, [&](drogon::ReqResult res, const drogon::HttpResponsePtr &resp) {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
if (res == drogon::ReqResult::Ok && resp) {
|
||||
result.status_code = resp->statusCode();
|
||||
result.body = resp->body();
|
||||
result.success = true;
|
||||
} else {
|
||||
result.status_code = 0;
|
||||
result.body = "";
|
||||
result.success = false;
|
||||
}
|
||||
done = true;
|
||||
cv.notify_one();
|
||||
loop.quit();
|
||||
}, timeout_seconds);
|
||||
|
||||
loop.loop();
|
||||
});
|
||||
|
||||
// Wait for completion
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mtx);
|
||||
cv.wait(lock, [&] { return done; });
|
||||
}
|
||||
|
||||
worker.join();
|
||||
return result;
|
||||
}
|
17
ipdemo/src/http_utils.hpp
Normal file
17
ipdemo/src/http_utils.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <drogon/HttpClient.h>
|
||||
#include <trantor/net/EventLoop.h>
|
||||
|
||||
struct HttpResponse {
|
||||
int status_code;
|
||||
std::string body;
|
||||
bool success;
|
||||
};
|
||||
|
||||
// Utility function for blocking HTTP GET requests
|
||||
HttpResponse http_get(const std::string& url, const std::string& path, bool use_https = false, double timeout_seconds = 10.0);
|
@ -1,12 +1,9 @@
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <drogon/drogon.h>
|
||||
#include "version.hpp"
|
||||
#include "assert.hpp"
|
||||
#include "http_utils.hpp"
|
||||
|
||||
void crashy() {
|
||||
ASSERT(false, "SUCCESS!");
|
||||
@ -17,42 +14,14 @@ int main() {
|
||||
std::cout << std::endl;
|
||||
std::cout << "Retrieving IP address..." << std::endl;
|
||||
|
||||
// Initialize drogon app but don't run it
|
||||
drogon::app().setLogLevel(trantor::Logger::kError);
|
||||
|
||||
std::string ip_body;
|
||||
int status = 0;
|
||||
bool done = false;
|
||||
|
||||
// Run in a separate thread to avoid event loop conflicts
|
||||
std::thread worker([&]() {
|
||||
trantor::EventLoop loop;
|
||||
auto client = drogon::HttpClient::newHttpClient("http://ipinfo.io", &loop);
|
||||
auto req = drogon::HttpRequest::newHttpRequest();
|
||||
req->setMethod(drogon::Get);
|
||||
req->setPath("/ip");
|
||||
|
||||
client->sendRequest(req, [&](drogon::ReqResult result, const drogon::HttpResponsePtr &resp) {
|
||||
if (result == drogon::ReqResult::Ok && resp) {
|
||||
ip_body = resp->body();
|
||||
status = resp->statusCode();
|
||||
} else {
|
||||
status = 0;
|
||||
}
|
||||
done = true;
|
||||
loop.quit();
|
||||
});
|
||||
|
||||
loop.loop();
|
||||
});
|
||||
|
||||
worker.join();
|
||||
// Use the utility function for HTTP GET
|
||||
auto response = http_get("ipinfo.io", "/ip", false, 10.0);
|
||||
|
||||
ASSERT(status == 200, "Failed to get IP");
|
||||
ASSERT(response.success && response.status_code == 200, "Failed to get IP");
|
||||
|
||||
nlohmann::json j;
|
||||
j["ip"] = ip_body;
|
||||
j["status"] = status;
|
||||
j["ip"] = response.body;
|
||||
j["status"] = response.status_code;
|
||||
|
||||
std::cout << j.dump(4) << std::endl;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user