diff --git a/.gitmodules b/.gitmodules index 72a74b8..5601c50 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "3rdparty/QHotkey"] path = 3rdparty/QHotkey url = https://github.com/Skycoder42/QHotkey.git +[submodule "3rdparty/cpp-httplib"] + path = 3rdparty/cpp-httplib + url = https://github.com/yhirose/cpp-httplib.git diff --git a/3rdparty/cpp-httplib b/3rdparty/cpp-httplib new file mode 160000 index 0000000..9b5f76f --- /dev/null +++ b/3rdparty/cpp-httplib @@ -0,0 +1 @@ +Subproject commit 9b5f76f8337d54c8f6a0920df2232ac74eff613b diff --git a/CMakeLists.txt b/CMakeLists.txt index 7321c0f..b6a165d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -107,6 +107,10 @@ else () list(APPEND NKR_EXTERNAL_TARGETS qhotkey) endif () +# if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") +# include_directories(3rdparty/cpp-httplib) +# endif() + #### debug print #### if (DBG_CMAKE) @@ -126,6 +130,7 @@ set(PROJECT_SOURCES main/NekoGui.cpp main/NekoGui_Utils.cpp main/HTTPRequestHelper.cpp + main/SimpleHttpClient.cpp 3rdparty/base64.cpp 3rdparty/qrcodegen.cpp diff --git a/main/HTTPRequestHelper.cpp b/main/HTTPRequestHelper.cpp index 62c8cd2..01b5e0f 100644 --- a/main/HTTPRequestHelper.cpp +++ b/main/HTTPRequestHelper.cpp @@ -7,6 +7,7 @@ #include #include "main/NekoGui.hpp" +#include "main/SimpleHttpClient.h" namespace NekoGui_network { @@ -44,6 +45,15 @@ namespace NekoGui_network { c.setPeerVerifyMode(QSslSocket::PeerVerifyMode::VerifyNone); request.setSslConfiguration(c); } + +#ifdef __GNUC__ + { + QNetworkAccessManagerAlternative::HttpClient syncClient; + auto res = syncClient.executeGetRequest(request, accessManager); + return NekoHTTPResponse{res.success ? "" : res.error, + res.body.toLocal8Bit(), res.headers}; + } +#else // auto _reply = accessManager.get(request); connect(_reply, &QNetworkReply::sslErrors, _reply, [](const QList &errors) { @@ -73,6 +83,7 @@ namespace NekoGui_network { _reply->readAll(), _reply->rawHeaderPairs()}; _reply->deleteLater(); return result; +#endif } QString NetworkRequestHelper::GetHeader(const QList> &header, const QString &name) { diff --git a/main/SimpleHttpClient.cpp b/main/SimpleHttpClient.cpp new file mode 100644 index 0000000..d65d7de --- /dev/null +++ b/main/SimpleHttpClient.cpp @@ -0,0 +1,73 @@ +#include "SimpleHttpClient.h" +#include "3rdparty/cpp-httplib/httplib.h" +#include + +#ifdef __GNUC__ + +QNetworkAccessManagerAlternative::HttpResult QNetworkAccessManagerAlternative::HttpClient::executeGetRequest(const QNetworkRequest &request, QNetworkAccessManager &manager) { + HttpResult result; + result.success = false; + result.statusCode = -1; + + QUrl url = request.url(); + if (!url.isValid() || (url.scheme() != "http" && url.scheme() != "https")) { + result.error = "Unsupported or invalid URL scheme"; + return result; + } + + // bool isHttps = (url.scheme() == "https"); + + QString host = url.host(); + // int port = (url.port() == -1) ? (isHttps ? 443 : 80) : url.port(); + + // httplib::Client client(host.toStdString(), port); + httplib::Client client(host.toStdString()); + +#ifdef CPPHTTPLIB_OPENSSL_SUPPORT + if (isHttps) { + client.enable_server_certificate_verification(false); // Skip SSL verification for demo + } +#endif + + QNetworkProxy proxy = manager.proxy(); + if (proxy.type() != QNetworkProxy::NoProxy) { + client.set_proxy( + proxy.hostName().toStdString(), + static_cast(proxy.port()) + ); + if(!proxy.user().isEmpty()) + client.set_proxy_basic_auth( + proxy.user().toStdString(), + proxy.password().toStdString() + ); + } + + httplib::Headers headers; + QList headerList = request.rawHeaderList(); + for (const QByteArray &header : headerList) { + headers.insert(std::pair{header.toStdString(), request.rawHeader(header).toStdString()}); + } + + auto const pathURL = url.path(); + auto res = client.Get(pathURL.toStdString()); + + if (res) { + result.statusCode = res->status; + for (const auto &header : res->headers) { + result.headers.append(qMakePair(QByteArray(header.first.c_str()), + QByteArray(header.second.c_str()))); + } + if (res->status == 200) { + result.success = true; + result.body = QString::fromStdString(res->body); + } else { + result.error = QString("HTTP Error: %1").arg(res->status); + } + } else { + result.error = QString::fromStdString(httplib::to_string(res.error())); + } + + return result; +} + +#endif diff --git a/main/SimpleHttpClient.h b/main/SimpleHttpClient.h new file mode 100644 index 0000000..d394435 --- /dev/null +++ b/main/SimpleHttpClient.h @@ -0,0 +1,31 @@ +#ifndef SIMPLEHTTPCLIENT_H +#define SIMPLEHTTPCLIENT_H + +#include +#include +#include +#include +#include +#include +#include + + +#ifdef __GNUC__ +namespace QNetworkAccessManagerAlternative{ + struct HttpResult { + bool success; // Success flag + QString body; // Response body + QList> headers; // Raw headers as key-value pairs + QString error; // Error message if not successful + int statusCode; // HTTP status code + }; + + class HttpClient { + public: + static HttpResult executeGetRequest(const QNetworkRequest &request, QNetworkAccessManager &manager); + }; + +} +#endif + +#endif // SIMPLEHTTPCLIENT_H