From ee137b2820a8ca39a41031a893c904725ca21cfc Mon Sep 17 00:00:00 2001 From: peri4 Date: Fri, 15 Nov 2024 14:18:49 +0300 Subject: [PATCH] http server options, remove old --- libs/http_server/microhttpd_server_p.cpp | 99 ++++++++++++--------- libs/http_server/pihttpserver.cpp | 1 - libs/main/core/pibase.h | 4 +- libs/main/http_server/microhttpd_server_p.h | 16 +++- main.cpp | 2 + 5 files changed, 70 insertions(+), 52 deletions(-) diff --git a/libs/http_server/microhttpd_server_p.cpp b/libs/http_server/microhttpd_server_p.cpp index fb89d1a3..d77577bc 100644 --- a/libs/http_server/microhttpd_server_p.cpp +++ b/libs/http_server/microhttpd_server_p.cpp @@ -1,8 +1,7 @@ #include "microhttpd_server_p.h" -#include "pidir.h" -#include "pifile.h" #include "piliterals_string.h" +#include "piliterals_time.h" #include @@ -29,29 +28,21 @@ bool MicrohttpdServerConnection::ready() { done = true; MicrohttpdServer::Reply rep; if (method == MicrohttpdServer::Method::Get) { - PIByteArray file = server->getFile(path); - if (!file.isEmpty()) { - rep.addHeader(MHD_HTTP_HEADER_CACHE_CONTROL, "public"); - rep.addHeader(MHD_HTTP_HEADER_CONTENT_TYPE, "application/octet-stream"); - rep.setBody(file); - send_reply(rep); - return true; - } if (path == "/favicon.ico"_a) { - piCout << "send favicon" << server->favicon.size() << "bytes"; + // piCout << "send favicon" << server->favicon.size() << "bytes"; rep.setBody(server->favicon); send_reply(rep); return true; } } - piCout << "ready" << (int)method << path; + // piCout << "ready" << (int)method << path; MicrohttpdServer::Request req; req.method = method; req.path = path; req.body = body; req.headers = headers; req.args = args; - // rep.headers = headers; + rep.setCode(MHD_HTTP_BAD_REQUEST); if (server->callback) rep = server->callback(req); rep.addFixedHeaders(); send_reply(rep); @@ -62,13 +53,13 @@ bool MicrohttpdServerConnection::ready() { int MicrohttpdServerConnection::send_reply(const MicrohttpdServer::Reply & r) { MHD_Response * response = MHD_create_response_from_buffer(r.body.size(), (void *)r.body.data(), MHD_RESPMEM_MUST_COPY); if (!response) { - piCout << "null response" << r.body.size() << (void *)r.body.data(); + // piCout << "null response" << r.body.size() << (void *)r.body.data(); return MHD_NO; } auto it = r.headers.makeIterator(); while (it.next()) MHD_add_response_header(response, it.key().dataAscii(), it.value().dataUTF8()); - piCout << "status" << r.code; + // piCout << "status" << r.code; int ret = MHD_queue_response(connection, r.code, response); MHD_destroy_response(response); return ret; @@ -80,6 +71,14 @@ int MicrohttpdServerConnection::send_error() { } +void log_callback(void * cls, const char * fm, va_list ap) { + MicrohttpdServer * server = (MicrohttpdServer *)cls; + piCout << "log" << server; + if (!server) return; + piCout << server << fm << ap; +} + + int iterate_post(void * conn_cls, MHD_ValueKind kind, const char * key, @@ -98,13 +97,14 @@ int iterate_post(void * conn_cls, void request_completed(void * cls, MHD_Connection * connection, void ** con_cls, MHD_RequestTerminationCode toe) { MicrohttpdServerConnection *& conn((MicrohttpdServerConnection *&)(*con_cls)); - // qDebug() << "request_completed" << conn << conn->headers << conn->post << '"' << conn->body << '"'; + // piCout << "request_completed" << conn << conn->headers << conn->post << '"' << conn->body << '"'; if (!conn) return; if (conn->method == MicrohttpdServer::Method::Post && conn->postprocessor) MHD_destroy_post_processor(conn->postprocessor); conn->ready(); piDeleteSafety(conn); } + int header_iterate(void * cls, MHD_ValueKind kind, const char * key, const char * value) { MicrohttpdServerConnection * conn = (MicrohttpdServerConnection *)cls; if (!conn) return MHD_NO; @@ -112,6 +112,7 @@ int header_iterate(void * cls, MHD_ValueKind kind, const char * key, const char return MHD_YES; } + int args_iterate(void * cls, MHD_ValueKind kind, const char * key, const char * value) { MicrohttpdServerConnection * conn = (MicrohttpdServerConnection *)cls; if (!conn) return MHD_NO; @@ -152,7 +153,9 @@ int answer_to_connection(void * cls, m = MicrohttpdServer::Method::Patch; if (m == MicrohttpdServer::Method::Unknown) { - piCout << "[MicrohttpdServer] Unknown method!"; + piCout << "[MicrohttpdServer]" + << "Warning:" + << "Unknown method!"; return MHD_NO; } @@ -204,7 +207,9 @@ PRIVATE_DEFINITION_END(MicrohttpdServer) MicrohttpdServer::MicrohttpdServer() { - PRIVATE->daemon = nullptr; + PRIVATE->daemon = nullptr; + opts[Option::ConnectionLimit] = FD_SETSIZE - 4; + opts[Option::ConnectionTimeout] = 0_s; } @@ -213,10 +218,8 @@ MicrohttpdServer::~MicrohttpdServer() { } -void MicrohttpdServer::setWWWRoot(const PIString & path) { - www_root = path; - if (www_root.isEmpty()) return; - www_root = PIDir(www_root).absolutePath(); +void MicrohttpdServer::setOption(Option o, PIVariant v) { + opts[o] = std::move(v); } @@ -229,26 +232,42 @@ bool MicrohttpdServer::listen(PINetworkAddress addr) { stop(); uint flags = 0; #if MHD_VERSION <= 0x00095100 - flags = MHD_USE_POLL_INTERNALLY; + flags |= MHD_USE_POLL_INTERNALLY; #else - flags = MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD; + flags |= MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD; #endif + if (opts.value(Option::HTTPSEnabled).toBool()) flags |= MHD_USE_TLS; + mem_key = opts.value(Option::HTTPSMemKey).toByteArray(); + if (mem_key.isNotEmpty()) mem_key.append(0); + mem_cert = opts.value(Option::HTTPSMemCert).toByteArray(); + if (mem_cert.isNotEmpty()) mem_cert.append(0); + key_pass = opts.value(Option::HTTPSKeyPassword).toByteArray(); + if (key_pass.isNotEmpty()) key_pass.append(0); sockaddr_in sa_addr; memset(&sa_addr, 0, sizeof(sa_addr)); sa_addr.sin_port = htons(addr.port()); sa_addr.sin_addr.s_addr = addr.ip(); sa_addr.sin_family = AF_INET; - PRIVATE->daemon = MHD_start_daemon(flags, + PIVector options; + options.append({MHD_OPTION_EXTERNAL_LOGGER, (intptr_t)log_callback, this}); + options.append({MHD_OPTION_NOTIFY_COMPLETED, (intptr_t)request_completed, nullptr}); + options.append({MHD_OPTION_CONNECTION_LIMIT, opts.value(Option::ConnectionLimit).toInt(), nullptr}); + options.append({MHD_OPTION_CONNECTION_TIMEOUT, piRound(opts.value(Option::ConnectionTimeout).toSystemTime().toSeconds()), nullptr}); + options.append({MHD_OPTION_SOCK_ADDR, 0, &sa_addr}); + if (opts.value(Option::HTTPSEnabled).toBool()) { + options.append({MHD_OPTION_HTTPS_MEM_KEY, 0, mem_key.data()}); + options.append({MHD_OPTION_HTTPS_MEM_CERT, 0, mem_cert.data()}); + options.append({MHD_OPTION_HTTPS_KEY_PASSWORD, 0, key_pass.data()}); + } + options.append({MHD_OPTION_END, 0, nullptr}); + PRIVATE->daemon = MHD_start_daemon(flags, addr.port(), nullptr, nullptr, (MHD_AccessHandlerCallback)answer_to_connection, this, - MHD_OPTION_NOTIFY_COMPLETED, - request_completed, - nullptr, - MHD_OPTION_SOCK_ADDR, - &sa_addr, + MHD_OPTION_ARRAY, + options.data(), MHD_OPTION_END); return isListen(); } @@ -259,16 +278,6 @@ bool MicrohttpdServer::isListen() const { } -PIByteArray MicrohttpdServer::getFile(PIString name) { - if (www_root.isEmpty()) return PIByteArray(); - if (name == "/") name += "index.html"; - PIString path = PIDir(www_root).relative(name); - // qDebug() << "getFile" << path; - if (path.isEmpty() || !path.startsWith(www_root)) return PIByteArray(); - return PIFile::readAll(PIDir(www_root).absolute(name)); -} - - void MicrohttpdServer::stop() { if (PRIVATE->daemon) { MHD_stop_daemon(PRIVATE->daemon); @@ -299,10 +308,12 @@ void MicrohttpdServer::Reply::setCode(int c) { void MicrohttpdServer::Reply::addFixedHeaders() { if (!headers.contains(MHD_HTTP_HEADER_CONTENT_TYPE)) { - if (body.startsWith(PIByteArray::fromAscii(""))) - addHeader(MHD_HTTP_HEADER_CONTENT_TYPE, "text/html; charset=utf-8"); - else - addHeader(MHD_HTTP_HEADER_CONTENT_TYPE, "application/json; charset=utf-8"); + if (body.isNotEmpty()) { + if (body.startsWith(PIByteArray::fromAscii(""))) + addHeader(MHD_HTTP_HEADER_CONTENT_TYPE, "text/html; charset=utf-8"); + else if (body[0] == '[' || body[0] == '{') + addHeader(MHD_HTTP_HEADER_CONTENT_TYPE, "application/json; charset=utf-8"); + } } addHeader(MHD_HTTP_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, "*"); } diff --git a/libs/http_server/pihttpserver.cpp b/libs/http_server/pihttpserver.cpp index f32a653e..3419ed42 100644 --- a/libs/http_server/pihttpserver.cpp +++ b/libs/http_server/pihttpserver.cpp @@ -13,7 +13,6 @@ PIHTTPServer::PIHTTPServer() { while (it.next()) { if (it.value().function) { if (it.value().match(in_path)) { - rep.setCode(200); rep = it.value().function(r); break; } diff --git a/libs/main/core/pibase.h b/libs/main/core/pibase.h index d04dbd04..8269137c 100644 --- a/libs/main/core/pibase.h +++ b/libs/main/core/pibase.h @@ -132,9 +132,7 @@ inline void piSwapBinary(const void *& f, const void *& s) { //! \~english Example:\n \snippet piincludes.cpp compareBinary //! \~russian Пример:\n \snippet piincludes.cpp compareBinary inline bool piCompareBinary(const void * f, const void * s, size_t size) { - for (size_t i = 0; i < size; ++i) - if (((const uchar *)f)[i] != ((const uchar *)s)[i]) return false; - return true; + return 0 == memcmp(f, s, size); } //! \~\brief diff --git a/libs/main/http_server/microhttpd_server_p.h b/libs/main/http_server/microhttpd_server_p.h index c26c31bf..5e8c526a 100644 --- a/libs/main/http_server/microhttpd_server_p.h +++ b/libs/main/http_server/microhttpd_server_p.h @@ -27,6 +27,14 @@ public: Trace, Patch }; + enum class Option { + ConnectionLimit, // uint + ConnectionTimeout, // uint, sec + HTTPSEnabled, // bool + HTTPSMemKey, // const char * to key.pem data + HTTPSMemCert, // const char * to cert.pem data + HTTPSKeyPassword // const char * to passwd for key.pem + }; struct PIP_HTTP_SERVER_EXPORT Request { MicrohttpdServer::Method method; @@ -52,7 +60,7 @@ public: PIMap headers; }; - void setWWWRoot(const PIString & path); + void setOption(Option o, PIVariant v); void setFavicon(const PIByteArray & im); bool listen(PINetworkAddress addr); @@ -63,12 +71,12 @@ public: void setRequestCallback(std::function c) { callback = c; } private: - PIByteArray getFile(PIString name); - PRIVATE_DECLARATION(PIP_HTTP_SERVER_EXPORT) - PIString www_root; + PIByteArray favicon; + PIMap opts; std::function callback; + PIByteArray mem_key, mem_cert, key_pass; }; diff --git a/main.cpp b/main.cpp index 4952e4d3..df656680 100644 --- a/main.cpp +++ b/main.cpp @@ -18,7 +18,9 @@ int main(int argc, char * argv[]) { PIHTTPServer server; server.setFavicon(PIFile::readAll("logo.png", false)); + // server.setOption(MicrohttpdServer::Option::HTTPSEnabled, true); server.listen({"127.0.0.1", 7777}); + // server.listen({"192.168.1.10", 7778}); server.registerPath("/", [](const MicrohttpdServer::Request & r) -> MicrohttpdServer::Reply { MicrohttpdServer::Reply ret;