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)
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)

View File

@ -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<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);
};
#endif

View File

@ -22,10 +22,10 @@ AppManager::AppManager()
//
// mHttpServerRuning = false;
}
const StatusCode AppManager::Init(void)
const StatusCode AppManager::Init(const AppParam &param)
{
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 &param)
{
auto httpServerThread = [](std::shared_ptr<AppManager> app) {
auto httpServerThread = [&param](std::shared_ptr<AppManager> 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 &param)
{
std::shared_ptr<AppManager> 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();
}

View File

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

View File

@ -28,5 +28,5 @@ std::shared_ptr<IAppManager> &IAppManager::GetInstance(std::shared_ptr<IAppManag
}
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); }

View File

@ -14,7 +14,6 @@
*/
#include "SixFrameHandle.h"
#include "ILog.h"
#include "cJSON.h"
#include <sstream>
#include <stdio.h>
using std::placeholders::_1;
@ -86,6 +85,17 @@ void SixFrameHandle::RequestGetProductInfo(std::multimap<std::string, std::strin
ResponseHandle responseHandle, void *context)
{
LogInfo("RequestGetProductInfo.\n");
responseHandle("hello world.", context);
// cJSON *monitor = cJSON_CreateObject();
char *resultStr = nullptr;
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
#include "IAppProtocolHandle.h"
#include "StatusCode.h"
#include <cJSON.h>
#include <functional>
#include <iostream>
#include <map>
#include <memory>
#include <vector>
using ResquesHandleFunc = std::function<void(std::multimap<std::string, std::string> &, ResponseHandle, void *)>;
enum class ResposeResult
{
SUCCESSFUL = 0,
FAILED,
END
};
class SixFrameHandle : public IAppProtocolHandle
{
public:
@ -40,6 +47,9 @@ private:
void RequestGetProductInfo(std::multimap<std::string, std::string> &paramsMap, ResponseHandle responseHandle,
void *context);
private:
cJSON *MakeResponseResult(const ResposeResult result);
private:
std::map<std::string, ResquesHandleFunc> mResquesHandleFunc;
};

View File

@ -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})

View File

@ -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

View File

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

View File

@ -27,3 +27,8 @@ void AppManagerTestTool::MockGetProductInfo(void)
//
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);
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);

View File

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

View File

@ -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);

View File

@ -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;

View File

@ -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
}

View File

@ -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");

View File

@ -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();