Improve:WebServer http post file.

This commit is contained in:
Fancy code 2024-03-01 22:41:22 -08:00
parent 3964a430ec
commit 202e502b90
18 changed files with 203 additions and 19 deletions

View File

@ -1,6 +1,9 @@
set(CMAKE_LEGACY_CYGWIN_WIN32 0) set(CMAKE_LEGACY_CYGWIN_WIN32 0)
cmake_minimum_required(VERSION 3.0) cmake_minimum_required(VERSION 3.0)
set(EXECUTABLE_OUTPUT_PATH ${EXEC_OUTPUT_PATH})
set(LIBRARY_OUTPUT_PATH ${LIBS_OUTPUT_PATH})
project(cJSON project(cJSON
VERSION 1.7.17 VERSION 1.7.17
LANGUAGES C) LANGUAGES C)

View File

@ -26,13 +26,19 @@ public:
VAppMonitor() = default; VAppMonitor() = default;
virtual ~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 class IAppManager
{ {
public: public:
IAppManager() = default; IAppManager() = default;
virtual ~IAppManager() = default; virtual ~IAppManager() = default;
static std::shared_ptr<IAppManager> &GetInstance(std::shared_ptr<IAppManager> *impl = nullptr); static std::shared_ptr<IAppManager> &GetInstance(std::shared_ptr<IAppManager> *impl = nullptr);
virtual const StatusCode Init(void); virtual const StatusCode Init(const AppParam &param);
virtual const StatusCode UnInit(void); virtual const StatusCode UnInit(void);
}; };
#endif #endif

View File

@ -22,10 +22,10 @@ AppManager::AppManager()
// //
// mHttpServerRuning = false; // mHttpServerRuning = false;
} }
const StatusCode AppManager::Init(void) const StatusCode AppManager::Init(const AppParam &param)
{ {
AppManagerMakePtr::GetInstance()->CreateProtocolHandle(mProtocolHandle); AppManagerMakePtr::GetInstance()->CreateProtocolHandle(mProtocolHandle);
HttpServerStart(); HttpServerStart(param);
return CreateStatusCode(STATUS_CODE_OK); return CreateStatusCode(STATUS_CODE_OK);
} }
const StatusCode AppManager::UnInit(void) 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); mProtocolHandle->RequestHandle(url, urlLength, responseHandle, context);
} }
void AppManager::HttpServerStart(void) void AppManager::HttpServerStart(const AppParam &param)
{ {
auto httpServerThread = [](std::shared_ptr<AppManager> app) { auto httpServerThread = [&param](std::shared_ptr<AppManager> app) {
LogInfo("AppManager httpServer started.\n"); LogInfo("AppManager httpServer started.\n");
app->HttpServerThread(); app->HttpServerThread(param);
}; };
mHttpSever = std::thread(httpServerThread, shared_from_this()); mHttpSever = std::thread(httpServerThread, shared_from_this());
} }
@ -56,7 +56,7 @@ void AppManager::HttpServerStop(void)
mHttpSever.join(); mHttpSever.join();
} }
} }
void AppManager::HttpServerThread(void) void AppManager::HttpServerThread(const AppParam &param)
{ {
std::shared_ptr<AppManager> app = shared_from_this(); std::shared_ptr<AppManager> app = shared_from_this();
auto httpHandle = auto httpHandle =
@ -70,8 +70,7 @@ void AppManager::HttpServerThread(void)
}; };
// FxHttpServerInit(httpHandle, 8080); // FxHttpServerInit(httpHandle, 8080);
// FxHttpServerUnInit(); // FxHttpServerUnInit();
WebServerParam web = { WebServerParam web = {.mIp = param.mIP, .mPort = param.mPort, .mHttpRequestHandle = httpHandle};
.mIp = APP_MANAGER_HTTP_SERVER_IP, .mPort = APP_MANAGER_HTTP_SERVER_PORT, .mHttpRequestHandle = httpHandle};
WebServerInit(web); WebServerInit(web);
WebServerUnInit(); WebServerUnInit();
} }

View File

@ -22,14 +22,14 @@ class AppManager : public IAppManager, public std::enable_shared_from_this<AppMa
public: public:
AppManager(); AppManager();
virtual ~AppManager() = default; virtual ~AppManager() = default;
const StatusCode Init(void) override; const StatusCode Init(const AppParam &param) override;
const StatusCode UnInit(void) override; const StatusCode UnInit(void) override;
void AppRequestHandle(const char *url, const unsigned int urlLength, ResponseHandle responseHandle, void *context); void AppRequestHandle(const char *url, const unsigned int urlLength, ResponseHandle responseHandle, void *context);
private: private:
void HttpServerStart(void); void HttpServerStart(const AppParam &param);
void HttpServerStop(void); void HttpServerStop(void);
void HttpServerThread(void); void HttpServerThread(const AppParam &param);
private: private:
// bool mHttpServerRuning; // bool mHttpServerRuning;

View File

@ -28,5 +28,5 @@ std::shared_ptr<IAppManager> &IAppManager::GetInstance(std::shared_ptr<IAppManag
} }
return instance; return instance;
} }
const StatusCode IAppManager::Init(void) { return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION); } const StatusCode IAppManager::Init(const AppParam &param) { return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION); }
const StatusCode IAppManager::UnInit(void) { return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION); } const StatusCode IAppManager::UnInit(void) { return CreateStatusCode(STATUS_CODE_VIRTUAL_FUNCTION); }

View File

@ -14,7 +14,6 @@
*/ */
#include "SixFrameHandle.h" #include "SixFrameHandle.h"
#include "ILog.h" #include "ILog.h"
#include "cJSON.h"
#include <sstream> #include <sstream>
#include <stdio.h> #include <stdio.h>
using std::placeholders::_1; using std::placeholders::_1;
@ -86,6 +85,17 @@ void SixFrameHandle::RequestGetProductInfo(std::multimap<std::string, std::strin
ResponseHandle responseHandle, void *context) ResponseHandle responseHandle, void *context)
{ {
LogInfo("RequestGetProductInfo.\n"); LogInfo("RequestGetProductInfo.\n");
responseHandle("hello world.", context); char *resultStr = nullptr;
// cJSON *monitor = cJSON_CreateObject(); cJSON *result = MakeResponseResult(ResposeResult::SUCCESSFUL);
resultStr = cJSON_Print(result);
responseHandle(resultStr, context);
free(resultStr);
cJSON_Delete(result);
}
cJSON *SixFrameHandle::MakeResponseResult(const ResposeResult result)
{
const char *RESPONSE_RESULT = "result";
cJSON *resultCJSON = cJSON_CreateObject();
cJSON_AddNumberToObject(resultCJSON, RESPONSE_RESULT, static_cast<int>(result));
return resultCJSON;
} }

View File

@ -16,12 +16,19 @@
#define SIX_FRAME_HANDLE_H #define SIX_FRAME_HANDLE_H
#include "IAppProtocolHandle.h" #include "IAppProtocolHandle.h"
#include "StatusCode.h" #include "StatusCode.h"
#include <cJSON.h>
#include <functional> #include <functional>
#include <iostream> #include <iostream>
#include <map> #include <map>
#include <memory> #include <memory>
#include <vector> #include <vector>
using ResquesHandleFunc = std::function<void(std::multimap<std::string, std::string> &, ResponseHandle, void *)>; using ResquesHandleFunc = std::function<void(std::multimap<std::string, std::string> &, ResponseHandle, void *)>;
enum class ResposeResult
{
SUCCESSFUL = 0,
FAILED,
END
};
class SixFrameHandle : public IAppProtocolHandle class SixFrameHandle : public IAppProtocolHandle
{ {
public: public:
@ -40,6 +47,9 @@ private:
void RequestGetProductInfo(std::multimap<std::string, std::string> &paramsMap, ResponseHandle responseHandle, void RequestGetProductInfo(std::multimap<std::string, std::string> &paramsMap, ResponseHandle responseHandle,
void *context); void *context);
private:
cJSON *MakeResponseResult(const ResposeResult result);
private: private:
std::map<std::string, ResquesHandleFunc> mResquesHandleFunc; std::map<std::string, ResquesHandleFunc> mResquesHandleFunc;
}; };

View File

@ -24,6 +24,18 @@ link_directories(
${EXTERNAL_LIBS_OUTPUT_PATH} ${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_FILES_MAIN)
aux_source_directory(./src SRC_FILES) aux_source_directory(./src SRC_FILES)
if(${TARGET_PLATFORM} MATCHES ${DEFINE_LINUX}) if(${TARGET_PLATFORM} MATCHES ${DEFINE_LINUX})

View File

@ -23,7 +23,7 @@ namespace AppManagerTest
class AppManagerTest : public testing::Test, public AppManagerTestTool class AppManagerTest : public testing::Test, public AppManagerTestTool
{ {
public: public:
AppManagerTest() {} AppManagerTest() : mAppParam(APP_MANAGER_HTTP_SERVER_IP, APP_MANAGER_HTTP_SERVER_PORT) {}
virtual ~AppManagerTest() {} virtual ~AppManagerTest() {}
static void SetUpTestCase() static void SetUpTestCase()
{ {
@ -46,14 +46,26 @@ public:
DestroyAppManagerModule(); DestroyAppManagerModule();
// DestroyAllKeysMock(); // DestroyAllKeysMock();
} }
protected:
const AppParam mAppParam;
}; };
// ../output_files/test/bin/AppManagerTest --gtest_filter=AppManagerTest.INTEGRATION_AppManager_EXAMPLE_Demo // ../output_files/test/bin/AppManagerTest --gtest_filter=AppManagerTest.INTEGRATION_AppManager_EXAMPLE_Demo
TEST_F(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)); std::this_thread::sleep_for(std::chrono::milliseconds(100));
MockGetProductInfo(); MockGetProductInfo();
std::this_thread::sleep_for(std::chrono::milliseconds(1000)); std::this_thread::sleep_for(std::chrono::milliseconds(1000));
IAppManager::GetInstance()->UnInit(); 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 } // namespace AppManagerTest

View File

@ -25,5 +25,6 @@ public:
protected: protected:
void MockGetProductInfo(void); void MockGetProductInfo(void);
void MockUploadFiles(void);
}; };
#endif #endif

View File

@ -27,3 +27,8 @@ void AppManagerTestTool::MockGetProductInfo(void)
// //
ServersMock::GetInstance()->MockGetProductInfo(); ServersMock::GetInstance()->MockGetProductInfo();
} }
void AppManagerTestTool::MockUploadFiles(void)
{
//
ServersMock::GetInstance()->MockUploadFiles();
}

View File

@ -52,7 +52,30 @@ void ServersMock::MockGetProductInfo(void)
char *replyStr = (char *)malloc(http->replyLength + 1); char *replyStr = (char *)malloc(http->replyLength + 1);
memset(replyStr, 0, http->replyLength + 1); memset(replyStr, 0, http->replyLength + 1);
memcpy(replyStr, http->reply, http->replyLength); 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); free(replyStr);
} }
DeleteServersHttp(http); DeleteServersHttp(http);

View File

@ -22,6 +22,7 @@ public:
virtual ~ServersMock() = default; virtual ~ServersMock() = default;
static std::shared_ptr<ServersMock> &GetInstance(std::shared_ptr<ServersMock> *impl = nullptr); static std::shared_ptr<ServersMock> &GetInstance(std::shared_ptr<ServersMock> *impl = nullptr);
virtual void MockGetProductInfo(void); virtual void MockGetProductInfo(void);
virtual void MockUploadFiles(void);
private: private:
std::string mServerUrl; std::string mServerUrl;

View File

@ -91,6 +91,7 @@ ServerHttp *NewServersHttp(const char *url);
void DeleteServersHttp(ServerHttp *ptr); void DeleteServersHttp(ServerHttp *ptr);
void HttpGet(ServerHttp *param); void HttpGet(ServerHttp *param);
void HttpPost(ServerHttp *param); void HttpPost(ServerHttp *param);
void HttpPostFile(ServerHttp *param);
void HttpPut(ServerHttp *param); void HttpPut(ServerHttp *param);
// FTP API // FTP API
ServerFtp *NewServersFtp(const char *url, const FtpsFlag ftpsFlag); ServerFtp *NewServersFtp(const char *url, const FtpsFlag ftpsFlag);

View File

@ -123,6 +123,62 @@ void HttpServersPost(ServerHttp *param)
} }
curl_global_cleanup(); 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) static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream)
{ {
size_t retcode; size_t retcode;

View File

@ -20,6 +20,7 @@ extern "C" {
#endif #endif
void HttpServersGet(ServerHttp *param); void HttpServersGet(ServerHttp *param);
void HttpServersPost(ServerHttp *param); void HttpServersPost(ServerHttp *param);
void HttpServersPostFile(ServerHttp *param);
void HttpServersPut(ServerHttp *param); void HttpServersPut(ServerHttp *param);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -37,6 +37,11 @@ void HttpPost(ServerHttp *param)
LogInfo("HttpPost\n"); LogInfo("HttpPost\n");
HttpServersPost(param); HttpServersPost(param);
} }
void HttpPostFile(ServerHttp *param)
{
LogInfo("HttpPostFile\n");
HttpServersPostFile(param);
}
void HttpPut(ServerHttp *param) void HttpPut(ServerHttp *param)
{ {
LogInfo("HttpPut\n"); LogInfo("HttpPut\n");

View File

@ -68,6 +68,39 @@ static bool AppRequestHandle(Webs *wp)
websDone(wp); websDone(wp);
return 1; 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) StatusCode WebServerInit(const WebServerParam webParam)
{ {
websSetDebug(1); websSetDebug(1);
@ -98,6 +131,12 @@ StatusCode WebServerInit(const WebServerParam webParam)
websDefineHandler("appRequestHandle", 0, AppRequestHandle, 0, 0); websDefineHandler("appRequestHandle", 0, AppRequestHandle, 0, 0);
websAddRoute("/app", "appRequestHandle", 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); websServiceEvents(&finished);
logmsg(1, "Instructed to exit\n"); logmsg(1, "Instructed to exit\n");
websClose(); websClose();