From 202e502b909cd2837e86a4e283bc18cf3d5558ec Mon Sep 17 00:00:00 2001 From: Fancy code <258828110.@qq.com> Date: Fri, 1 Mar 2024 22:41:22 -0800 Subject: [PATCH] Improve:WebServer http post file. --- external/cJSON-1.7.17/CMakeLists.txt | 3 + middleware/AppManager/include/IAppManager.h | 8 ++- middleware/AppManager/src/AppManager.cpp | 15 +++-- middleware/AppManager/src/AppManager.h | 6 +- middleware/AppManager/src/IAppManager.cpp | 2 +- .../src/Protocol/SixFrame/SixFrameHandle.cpp | 16 +++++- .../src/Protocol/SixFrame/SixFrameHandle.h | 10 ++++ test/middleware/AppManager/CMakeLists.txt | 12 ++++ .../AppManager/src/AppManager_Test.cpp | 16 +++++- .../tool/include/AppManagerTestTool.h | 1 + .../tool/src/AppManagerTestTool.cpp | 5 ++ .../AppManager/tool/src/ServersMock.cpp | 25 ++++++++- .../AppManager/tool/src/ServersMock.h | 1 + utils/Servers/include/servers.h | 1 + utils/Servers/src/http_servers.c | 56 +++++++++++++++++++ utils/Servers/src/http_servers.h | 1 + utils/Servers/src/servers.c | 5 ++ utils/WebServer/src/WebServer.cpp | 39 +++++++++++++ 18 files changed, 203 insertions(+), 19 deletions(-) diff --git a/external/cJSON-1.7.17/CMakeLists.txt b/external/cJSON-1.7.17/CMakeLists.txt index 90acf9f..69b7ce6 100644 --- a/external/cJSON-1.7.17/CMakeLists.txt +++ b/external/cJSON-1.7.17/CMakeLists.txt @@ -1,6 +1,9 @@ set(CMAKE_LEGACY_CYGWIN_WIN32 0) cmake_minimum_required(VERSION 3.0) +set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH}) +set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH}) + project(cJSON VERSION 1.7.17 LANGUAGES C) diff --git a/middleware/AppManager/include/IAppManager.h b/middleware/AppManager/include/IAppManager.h index ad529bc..187ef98 100644 --- a/middleware/AppManager/include/IAppManager.h +++ b/middleware/AppManager/include/IAppManager.h @@ -26,13 +26,19 @@ public: VAppMonitor() = default; virtual ~VAppMonitor() = default; }; +typedef struct app_param +{ + app_param(const char *ip, const int port) : mIP(ip), mPort(port) {} + const char *mIP; + const int mPort; +} AppParam; class IAppManager { public: IAppManager() = default; virtual ~IAppManager() = default; static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); - virtual const StatusCode Init(void); + virtual const StatusCode Init(const AppParam ¶m); virtual const StatusCode UnInit(void); }; #endif \ No newline at end of file diff --git a/middleware/AppManager/src/AppManager.cpp b/middleware/AppManager/src/AppManager.cpp index bbac87d..e0b388b 100644 --- a/middleware/AppManager/src/AppManager.cpp +++ b/middleware/AppManager/src/AppManager.cpp @@ -22,10 +22,10 @@ AppManager::AppManager() // // mHttpServerRuning = false; } -const StatusCode AppManager::Init(void) +const StatusCode AppManager::Init(const AppParam ¶m) { AppManagerMakePtr::GetInstance()->CreateProtocolHandle(mProtocolHandle); - HttpServerStart(); + HttpServerStart(param); return CreateStatusCode(STATUS_CODE_OK); } const StatusCode AppManager::UnInit(void) @@ -40,11 +40,11 @@ void AppManager::AppRequestHandle(const char *url, const unsigned int urlLength, // mProtocolHandle->RequestHandle(url, urlLength, responseHandle, context); } -void AppManager::HttpServerStart(void) +void AppManager::HttpServerStart(const AppParam ¶m) { - auto httpServerThread = [](std::shared_ptr app) { + auto httpServerThread = [¶m](std::shared_ptr app) { LogInfo("AppManager httpServer started.\n"); - app->HttpServerThread(); + app->HttpServerThread(param); }; mHttpSever = std::thread(httpServerThread, shared_from_this()); } @@ -56,7 +56,7 @@ void AppManager::HttpServerStop(void) mHttpSever.join(); } } -void AppManager::HttpServerThread(void) +void AppManager::HttpServerThread(const AppParam ¶m) { std::shared_ptr app = shared_from_this(); auto httpHandle = @@ -70,8 +70,7 @@ void AppManager::HttpServerThread(void) }; // FxHttpServerInit(httpHandle, 8080); // FxHttpServerUnInit(); - WebServerParam web = { - .mIp = APP_MANAGER_HTTP_SERVER_IP, .mPort = APP_MANAGER_HTTP_SERVER_PORT, .mHttpRequestHandle = httpHandle}; + WebServerParam web = {.mIp = param.mIP, .mPort = param.mPort, .mHttpRequestHandle = httpHandle}; WebServerInit(web); WebServerUnInit(); } \ No newline at end of file diff --git a/middleware/AppManager/src/AppManager.h b/middleware/AppManager/src/AppManager.h index d807222..d9542cb 100644 --- a/middleware/AppManager/src/AppManager.h +++ b/middleware/AppManager/src/AppManager.h @@ -22,14 +22,14 @@ class AppManager : public IAppManager, public std::enable_shared_from_this &IAppManager::GetInstance(std::shared_ptr #include using std::placeholders::_1; @@ -86,6 +85,17 @@ void SixFrameHandle::RequestGetProductInfo(std::multimap(result)); + return resultCJSON; } \ No newline at end of file diff --git a/middleware/AppManager/src/Protocol/SixFrame/SixFrameHandle.h b/middleware/AppManager/src/Protocol/SixFrame/SixFrameHandle.h index 0b65a58..5a8902b 100644 --- a/middleware/AppManager/src/Protocol/SixFrame/SixFrameHandle.h +++ b/middleware/AppManager/src/Protocol/SixFrame/SixFrameHandle.h @@ -16,12 +16,19 @@ #define SIX_FRAME_HANDLE_H #include "IAppProtocolHandle.h" #include "StatusCode.h" +#include #include #include #include #include #include using ResquesHandleFunc = std::function &, ResponseHandle, void *)>; +enum class ResposeResult +{ + SUCCESSFUL = 0, + FAILED, + END +}; class SixFrameHandle : public IAppProtocolHandle { public: @@ -40,6 +47,9 @@ private: void RequestGetProductInfo(std::multimap ¶msMap, ResponseHandle responseHandle, void *context); +private: + cJSON *MakeResponseResult(const ResposeResult result); + private: std::map mResquesHandleFunc; }; diff --git a/test/middleware/AppManager/CMakeLists.txt b/test/middleware/AppManager/CMakeLists.txt index dafeb26..cb89bc4 100644 --- a/test/middleware/AppManager/CMakeLists.txt +++ b/test/middleware/AppManager/CMakeLists.txt @@ -24,6 +24,18 @@ link_directories( ${EXTERNAL_LIBS_OUTPUT_PATH} ) +if (NOT DEFINED APP_MANAGER_HTTP_SERVER_IP) + set(APP_MANAGER_HTTP_SERVER_IP "localhost") +endif() +add_definitions(-DAPP_MANAGER_HTTP_SERVER_IP=\"${APP_MANAGER_HTTP_SERVER_IP}\") + +if (NOT DEFINED APP_MANAGER_HTTP_SERVER_PORT) + message(FATAL_ERROR "You should set http listen port. + Example: set(APP_MANAGER_HTTP_SERVER_PORT \"8888\") + Refer to:${CMAKE_SOURCE_DIR_IPCSDK}/builde/cmake/toolchain/linux.toolchain.cmake") +endif() +add_definitions(-DAPP_MANAGER_HTTP_SERVER_PORT=${APP_MANAGER_HTTP_SERVER_PORT}) + aux_source_directory(. SRC_FILES_MAIN) aux_source_directory(./src SRC_FILES) if(${TARGET_PLATFORM} MATCHES ${DEFINE_LINUX}) diff --git a/test/middleware/AppManager/src/AppManager_Test.cpp b/test/middleware/AppManager/src/AppManager_Test.cpp index d3cae89..d1bafe9 100644 --- a/test/middleware/AppManager/src/AppManager_Test.cpp +++ b/test/middleware/AppManager/src/AppManager_Test.cpp @@ -23,7 +23,7 @@ namespace AppManagerTest class AppManagerTest : public testing::Test, public AppManagerTestTool { public: - AppManagerTest() {} + AppManagerTest() : mAppParam(APP_MANAGER_HTTP_SERVER_IP, APP_MANAGER_HTTP_SERVER_PORT) {} virtual ~AppManagerTest() {} static void SetUpTestCase() { @@ -46,14 +46,26 @@ public: DestroyAppManagerModule(); // DestroyAllKeysMock(); } + +protected: + const AppParam mAppParam; }; // ../output_files/test/bin/AppManagerTest --gtest_filter=AppManagerTest.INTEGRATION_AppManager_EXAMPLE_Demo TEST_F(AppManagerTest, INTEGRATION_AppManager_EXAMPLE_Demo) { - IAppManager::GetInstance()->Init(); + IAppManager::GetInstance()->Init(mAppParam); std::this_thread::sleep_for(std::chrono::milliseconds(100)); MockGetProductInfo(); std::this_thread::sleep_for(std::chrono::milliseconds(1000)); IAppManager::GetInstance()->UnInit(); } +// ../output_files/test/bin/AppManagerTest --gtest_filter=AppManagerTest.INTEGRATION_AppManager_EXAMPLE_Demo2 +TEST_F(AppManagerTest, INTEGRATION_AppManager_EXAMPLE_Demo2) +{ + IAppManager::GetInstance()->Init(mAppParam); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + MockUploadFiles(); + std::this_thread::sleep_for(std::chrono::milliseconds(10000)); + IAppManager::GetInstance()->UnInit(); +} } // namespace AppManagerTest \ No newline at end of file diff --git a/test/middleware/AppManager/tool/include/AppManagerTestTool.h b/test/middleware/AppManager/tool/include/AppManagerTestTool.h index 380e96a..4ac1423 100644 --- a/test/middleware/AppManager/tool/include/AppManagerTestTool.h +++ b/test/middleware/AppManager/tool/include/AppManagerTestTool.h @@ -25,5 +25,6 @@ public: protected: void MockGetProductInfo(void); + void MockUploadFiles(void); }; #endif \ No newline at end of file diff --git a/test/middleware/AppManager/tool/src/AppManagerTestTool.cpp b/test/middleware/AppManager/tool/src/AppManagerTestTool.cpp index 4e4b1fe..d3d7fff 100644 --- a/test/middleware/AppManager/tool/src/AppManagerTestTool.cpp +++ b/test/middleware/AppManager/tool/src/AppManagerTestTool.cpp @@ -26,4 +26,9 @@ void AppManagerTestTool::MockGetProductInfo(void) { // ServersMock::GetInstance()->MockGetProductInfo(); +} +void AppManagerTestTool::MockUploadFiles(void) +{ + // + ServersMock::GetInstance()->MockUploadFiles(); } \ No newline at end of file diff --git a/test/middleware/AppManager/tool/src/ServersMock.cpp b/test/middleware/AppManager/tool/src/ServersMock.cpp index cf67d23..50a5ccd 100644 --- a/test/middleware/AppManager/tool/src/ServersMock.cpp +++ b/test/middleware/AppManager/tool/src/ServersMock.cpp @@ -52,7 +52,30 @@ void ServersMock::MockGetProductInfo(void) char *replyStr = (char *)malloc(http->replyLength + 1); memset(replyStr, 0, http->replyLength + 1); memcpy(replyStr, http->reply, http->replyLength); - LogInfo("HttpGet response : %s\n", replyStr); + LogInfo("HttpGet response :\n%s\n", replyStr); + free(replyStr); + } + DeleteServersHttp(http); + } +} +void ServersMock::MockUploadFiles(void) +{ + ServerParam init = { + .logFlag = LOG_FLAG_ENABLE, + .sslVerifyFlag = SSL_VERIFY_DISABLE, + }; + ServersInit(init); + LogInfo("servers test start.\n"); + std::string mockRequest = mServerUrl + "/upload"; + ServerHttp *http = NewServersHttp(mockRequest.c_str()); + if (http) { + http->filePath = (char *)"./web/test.mp4"; + HttpPostFile(http); + if (http->reply) { + char *replyStr = (char *)malloc(http->replyLength + 1); + memset(replyStr, 0, http->replyLength + 1); + memcpy(replyStr, http->reply, http->replyLength); + LogInfo("HttpPost response :\n%s\n", replyStr); free(replyStr); } DeleteServersHttp(http); diff --git a/test/middleware/AppManager/tool/src/ServersMock.h b/test/middleware/AppManager/tool/src/ServersMock.h index ffae11b..86404e8 100644 --- a/test/middleware/AppManager/tool/src/ServersMock.h +++ b/test/middleware/AppManager/tool/src/ServersMock.h @@ -22,6 +22,7 @@ public: virtual ~ServersMock() = default; static std::shared_ptr &GetInstance(std::shared_ptr *impl = nullptr); virtual void MockGetProductInfo(void); + virtual void MockUploadFiles(void); private: std::string mServerUrl; diff --git a/utils/Servers/include/servers.h b/utils/Servers/include/servers.h index 9c48c14..e7bf7ea 100644 --- a/utils/Servers/include/servers.h +++ b/utils/Servers/include/servers.h @@ -91,6 +91,7 @@ ServerHttp *NewServersHttp(const char *url); void DeleteServersHttp(ServerHttp *ptr); void HttpGet(ServerHttp *param); void HttpPost(ServerHttp *param); +void HttpPostFile(ServerHttp *param); void HttpPut(ServerHttp *param); // FTP API ServerFtp *NewServersFtp(const char *url, const FtpsFlag ftpsFlag); diff --git a/utils/Servers/src/http_servers.c b/utils/Servers/src/http_servers.c index 56ae5c7..99e88b5 100644 --- a/utils/Servers/src/http_servers.c +++ b/utils/Servers/src/http_servers.c @@ -123,6 +123,62 @@ void HttpServersPost(ServerHttp *param) } curl_global_cleanup(); } +void HttpServersPostFile(ServerHttp *param) +{ + if (!param) { + LogError("null pointer.\n"); + return; + } + CURL *curl = NULL; + CURLcode res; + + struct curl_httppost *formpost = NULL; + struct curl_httppost *lastptr = NULL; + struct curl_slist *headerlist = NULL; + static const char buf[] = "Expect:"; + + curl_global_init(CURL_GLOBAL_ALL); + + /* Fill in the file upload field */ + curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "sendfile", CURLFORM_FILE, param->filePath, CURLFORM_END); + + /* Fill in the filename field */ + curl_formadd( + &formpost, &lastptr, CURLFORM_COPYNAME, "filename", CURLFORM_COPYCONTENTS, param->filePath, CURLFORM_END); + + /* Fill in the submit field too, even if this is rarely needed */ + curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "submit", CURLFORM_COPYCONTENTS, "send", CURLFORM_END); + + /* get a curl handle */ + curl = CurlEasyMake(); + /* initialize custom header list (stating that Expect: 100-continue is not + wanted */ + headerlist = curl_slist_append(headerlist, buf); + if (curl) { + /* what URL that receives this POST */ + curl_easy_setopt(curl, CURLOPT_URL, param->url); + // if((argc == 2) && (!strcmp(argv[1], "noexpectheader"))) + /* only disable 100-continue header if explicitly requested */ + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist); + curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); + + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_cb); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, param); + /* Perform the request, res will get the return code */ + res = curl_easy_perform(curl); + /* Check for errors */ + if (res != CURLE_OK) + fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); + + /* always cleanup */ + curl_easy_cleanup(curl); + + /* then cleanup the formpost chain */ + curl_formfree(formpost); + /* free slist */ + curl_slist_free_all(headerlist); + } +} static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream) { size_t retcode; diff --git a/utils/Servers/src/http_servers.h b/utils/Servers/src/http_servers.h index 0f11370..fbeef1d 100644 --- a/utils/Servers/src/http_servers.h +++ b/utils/Servers/src/http_servers.h @@ -20,6 +20,7 @@ extern "C" { #endif void HttpServersGet(ServerHttp *param); void HttpServersPost(ServerHttp *param); +void HttpServersPostFile(ServerHttp *param); void HttpServersPut(ServerHttp *param); #ifdef __cplusplus } diff --git a/utils/Servers/src/servers.c b/utils/Servers/src/servers.c index 62a3411..8ccc7cc 100644 --- a/utils/Servers/src/servers.c +++ b/utils/Servers/src/servers.c @@ -37,6 +37,11 @@ void HttpPost(ServerHttp *param) LogInfo("HttpPost\n"); HttpServersPost(param); } +void HttpPostFile(ServerHttp *param) +{ + LogInfo("HttpPostFile\n"); + HttpServersPostFile(param); +} void HttpPut(ServerHttp *param) { LogInfo("HttpPut\n"); diff --git a/utils/WebServer/src/WebServer.cpp b/utils/WebServer/src/WebServer.cpp index a81c4c6..a6e8468 100644 --- a/utils/WebServer/src/WebServer.cpp +++ b/utils/WebServer/src/WebServer.cpp @@ -68,6 +68,39 @@ static bool AppRequestHandle(Webs *wp) websDone(wp); return 1; } +static bool AppUploadHandle(Webs *wp) +{ + WebsKey *s; + WebsUpload *up; + char *upfile; + + websSetStatus(wp, 200); + websWriteHeaders(wp, -1, 0); + websWriteHeader(wp, "Content-Type", "text/plain"); + websWriteEndHeaders(wp); + + if (scaselessmatch(wp->method, "POST")) { + for (s = hashFirst(wp->files); s; s = hashNext(wp->files, s)) { + up = (WebsUpload *)s->content.value.symbol; + websWrite(wp, "FILE: %s\r\n", s->name.value.string); + websWrite(wp, "FILENAME=%s\r\n", up->filename); + websWrite(wp, "CLIENT=%s\r\n", up->clientFilename); + websWrite(wp, "TYPE=%s\r\n", up->contentType); + websWrite(wp, "SIZE=%d\r\n", up->size); + upfile = sfmt("%s/tmp/%s", websGetDocuments(), up->clientFilename); + if (rename(up->filename, upfile) < 0) { + error("Cannot rename uploaded file: %s to %s, errno %d", up->filename, upfile, errno); + } + wfree(upfile); + } + websWrite(wp, "\r\nVARS:\r\n"); + for (s = hashFirst(wp->vars); s; s = hashNext(wp->vars, s)) { + websWrite(wp, "%s=%s\r\n", s->name.value.string, s->content.value.string); + } + } + websDone(wp); + return 1; +} StatusCode WebServerInit(const WebServerParam webParam) { websSetDebug(1); @@ -98,6 +131,12 @@ StatusCode WebServerInit(const WebServerParam webParam) websDefineHandler("appRequestHandle", 0, AppRequestHandle, 0, 0); websAddRoute("/app", "appRequestHandle", 0); } + if (nullptr != webParam.mHttpRequestHandle) { + // gHttpHandle = webParam.mHttpRequestHandle; + websDefineHandler("AppUploadHandle", 0, AppUploadHandle, 0, 0); + websAddRoute("/upload", "AppUploadHandle", 0); + // websUrlHandlerDefine("/upload", (void *)AppUploadHandle); + } websServiceEvents(&finished); logmsg(1, "Instructed to exit\n"); websClose();