add http_client library, using libcurl
take out common http entities to http_common dir
This commit is contained in:
@@ -97,7 +97,7 @@ set(PIP_UTILS_LIST)
|
|||||||
set(PIP_TESTS_LIST)
|
set(PIP_TESTS_LIST)
|
||||||
set(PIP_EXPORTS)
|
set(PIP_EXPORTS)
|
||||||
|
|
||||||
set(PIP_SRC_MODULES "console;crypt;compress;usb;fftw;opencl;io_utils;client_server;cloud;lua;http_server")
|
set(PIP_SRC_MODULES "console;crypt;compress;usb;fftw;opencl;io_utils;client_server;cloud;lua;http_client;http_server")
|
||||||
foreach(_m ${PIP_SRC_MODULES})
|
foreach(_m ${PIP_SRC_MODULES})
|
||||||
set(PIP_MSG_${_m} "no")
|
set(PIP_MSG_${_m} "no")
|
||||||
endforeach()
|
endforeach()
|
||||||
@@ -498,10 +498,8 @@ if (NOT CROSSTOOLS)
|
|||||||
list(APPEND HDRS ${_lua_src_hdr})
|
list(APPEND HDRS ${_lua_src_hdr})
|
||||||
|
|
||||||
# libmicrohttpd
|
# libmicrohttpd
|
||||||
find_library(microhttpd_LIBRARIES microhttpd HINTS "${MINGW_LIB}")
|
pip_find_lib(microhttpd HINTS "${MINGW_LIB}")
|
||||||
set(microhttpd_FOUND FALSE)
|
if (microhttpd_FOUND)
|
||||||
if (microhttpd_LIBRARIES)
|
|
||||||
set(microhttpd_FOUND TRUE)
|
|
||||||
set(_microhttpd_add_libs microhttpd)
|
set(_microhttpd_add_libs microhttpd)
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
if("${C_COMPILER}" STREQUAL "cl.exe")
|
if("${C_COMPILER}" STREQUAL "cl.exe")
|
||||||
@@ -528,6 +526,12 @@ if (NOT CROSSTOOLS)
|
|||||||
pip_module(http_server "${_microhttpd_add_libs}" "PIP HTTP server" "" "" "")
|
pip_module(http_server "${_microhttpd_add_libs}" "PIP HTTP server" "" "" "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# libcurl
|
||||||
|
pip_find_lib(curl HINTS "${MINGW_LIB}")
|
||||||
|
if (curl_FOUND)
|
||||||
|
pip_module(http_client curl "PIP HTTP client" "" "" "")
|
||||||
|
endif()
|
||||||
|
|
||||||
# Test program
|
# Test program
|
||||||
if(PIP_UTILS)
|
if(PIP_UTILS)
|
||||||
|
|
||||||
@@ -535,9 +539,9 @@ if (NOT CROSSTOOLS)
|
|||||||
#target_link_libraries(pip_plugin pip)
|
#target_link_libraries(pip_plugin pip)
|
||||||
|
|
||||||
if (NOT DEFINED ANDROID_PLATFORM)
|
if (NOT DEFINED ANDROID_PLATFORM)
|
||||||
if(microhttpd_FOUND)
|
if(curl_FOUND)
|
||||||
add_executable(pip_test "main.cpp")
|
add_executable(pip_test "main.cpp")
|
||||||
target_link_libraries(pip_test pip pip_io_utils pip_client_server pip_http_server)
|
target_link_libraries(pip_test pip pip_io_utils pip_client_server pip_http_server pip_http_client)
|
||||||
if(sodium_FOUND)
|
if(sodium_FOUND)
|
||||||
add_executable(pip_cloud_test "main_picloud_test.cpp")
|
add_executable(pip_cloud_test "main_picloud_test.cpp")
|
||||||
target_link_libraries(pip_cloud_test pip_cloud)
|
target_link_libraries(pip_cloud_test pip_cloud)
|
||||||
@@ -667,7 +671,7 @@ if ((NOT PIP_FREERTOS) AND (NOT CROSSTOOLS))
|
|||||||
find_package(Doxygen)
|
find_package(Doxygen)
|
||||||
if(DOXYGEN_FOUND)
|
if(DOXYGEN_FOUND)
|
||||||
set(DOXY_DEFINES "${PIP_EXPORTS}")
|
set(DOXY_DEFINES "${PIP_EXPORTS}")
|
||||||
foreach (_m "console" "usb" "compress" "crypt" "client_server" "cloud" "fftw" "opencl" "io_utils" "lua")
|
foreach (_m "console" "usb" "compress" "crypt" "client_server" "cloud" "fftw" "opencl" "io_utils" "lua" "http_server" "http_client")
|
||||||
string(TOUPPER "${_m}" _mdef)
|
string(TOUPPER "${_m}" _mdef)
|
||||||
list(APPEND DOXY_DEFINES "PIP_${_mdef}_EXPORT")
|
list(APPEND DOXY_DEFINES "PIP_${_mdef}_EXPORT")
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ Create imported targets:
|
|||||||
* PIP::ClientServer
|
* PIP::ClientServer
|
||||||
* PIP::Cloud
|
* PIP::Cloud
|
||||||
* PIP::Lua
|
* PIP::Lua
|
||||||
|
* PIP::HTTPClient
|
||||||
* PIP::HTTPServer
|
* PIP::HTTPServer
|
||||||
|
|
||||||
These targets include directories and depends on
|
These targets include directories and depends on
|
||||||
@@ -27,7 +28,7 @@ shstk_set_find_dirs(PIP)
|
|||||||
set(__libs "usb;crypt;console;fftw;compress;opencl;io_utils;client_server;cloud;lua;http_server")
|
set(__libs "usb;crypt;console;fftw;compress;opencl;io_utils;client_server;cloud;lua;http_server")
|
||||||
|
|
||||||
if (BUILDING_PIP)
|
if (BUILDING_PIP)
|
||||||
#set(_libs "pip;pip_usb;pip_console;pip_crypt;pip_fftw;pip_compress;pip_opencl;pip_io_utils;pip_cloud;pip_lua;pip_http_server")
|
#set(_libs "pip;pip_usb;pip_console;pip_crypt;pip_fftw;pip_compress;pip_opencl;pip_io_utils;pip_cloud;pip_lua;pip_http_client;pip_http_server")
|
||||||
#set(_bins "pip_cmg;pip_rc;deploy_tool")
|
#set(_bins "pip_cmg;pip_rc;deploy_tool")
|
||||||
#get_target_property(_path pip BINARY_DIR)
|
#get_target_property(_path pip BINARY_DIR)
|
||||||
#get_target_property(_path pip LIBRARY_OUTPUT_NAME)
|
#get_target_property(_path pip LIBRARY_OUTPUT_NAME)
|
||||||
@@ -97,6 +98,7 @@ set(__module_io_utils IOUtils )
|
|||||||
set(__module_client_server ClientServer)
|
set(__module_client_server ClientServer)
|
||||||
set(__module_cloud Cloud )
|
set(__module_cloud Cloud )
|
||||||
set(__module_lua Lua )
|
set(__module_lua Lua )
|
||||||
|
set(__module_http_client HTTPClient )
|
||||||
set(__module_http_server HTTPServer )
|
set(__module_http_server HTTPServer )
|
||||||
|
|
||||||
foreach (_l ${__libs})
|
foreach (_l ${__libs})
|
||||||
|
|||||||
75
libs/http_client/curl_thread_pool_p.cpp
Normal file
75
libs/http_client/curl_thread_pool_p.cpp
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
|
||||||
|
#include "curl_thread_pool_p.h"
|
||||||
|
|
||||||
|
#include "pihttpclient.h"
|
||||||
|
#include "pitime.h"
|
||||||
|
|
||||||
|
|
||||||
|
CurlThreadPool::CurlThreadPool() {
|
||||||
|
piForTimes(10) {
|
||||||
|
auto * t = new PIThread([this]() { threadFunc(); }, true);
|
||||||
|
threads << t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CurlThreadPool::~CurlThreadPool() {
|
||||||
|
exiting = true;
|
||||||
|
for (auto * t: threads)
|
||||||
|
t->stop();
|
||||||
|
{
|
||||||
|
auto cr = clients.getRef();
|
||||||
|
for (auto c: *cr)
|
||||||
|
c->abort();
|
||||||
|
}
|
||||||
|
sem.release(threads.size());
|
||||||
|
for (auto * t: threads) {
|
||||||
|
t->waitForFinish();
|
||||||
|
t->setDebug(false);
|
||||||
|
t->terminate();
|
||||||
|
}
|
||||||
|
piDeleteAllAndClear(threads);
|
||||||
|
{
|
||||||
|
auto cr = clients.getRef();
|
||||||
|
for (auto c: *cr)
|
||||||
|
delete c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CurlThreadPool::threadFunc() {
|
||||||
|
if (exiting) return;
|
||||||
|
// piCout << "threadFuncl w ...";
|
||||||
|
sem.acquire();
|
||||||
|
// piCout << "threadFuncl wdone";
|
||||||
|
if (exiting) return;
|
||||||
|
PIHTTPClient * c = nullptr;
|
||||||
|
{
|
||||||
|
auto cr = clients.getRef();
|
||||||
|
if (cr->isEmpty()) return;
|
||||||
|
c = cr->dequeue();
|
||||||
|
// piCout << "threadFuncl get c";
|
||||||
|
}
|
||||||
|
// piCout << "threadFuncl proc c";
|
||||||
|
procClient(c);
|
||||||
|
// piCout << "threadFuncl end";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CurlThreadPool::procClient(PIHTTPClient * c) {
|
||||||
|
if (c->init()) c->perform();
|
||||||
|
delete c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CurlThreadPool::registerClient(PIHTTPClient * c) {
|
||||||
|
clients.getRef()->enqueue(c);
|
||||||
|
sem.release();
|
||||||
|
// piCout << "registerClient";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CurlThreadPool * CurlThreadPool::instance() {
|
||||||
|
static CurlThreadPool ret;
|
||||||
|
return &ret;
|
||||||
|
}
|
||||||
32
libs/http_client/curl_thread_pool_p.h
Normal file
32
libs/http_client/curl_thread_pool_p.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef curl_thread_pool_p_H
|
||||||
|
#define curl_thread_pool_p_H
|
||||||
|
|
||||||
|
#include "piconditionvar.h"
|
||||||
|
#include "piprotectedvariable.h"
|
||||||
|
#include "pisemaphore.h"
|
||||||
|
#include "pithread.h"
|
||||||
|
|
||||||
|
class PIHTTPClient;
|
||||||
|
|
||||||
|
class CurlThreadPool {
|
||||||
|
public:
|
||||||
|
void registerClient(PIHTTPClient * c);
|
||||||
|
|
||||||
|
static CurlThreadPool * instance();
|
||||||
|
|
||||||
|
private:
|
||||||
|
NO_COPY_CLASS(CurlThreadPool)
|
||||||
|
CurlThreadPool();
|
||||||
|
~CurlThreadPool();
|
||||||
|
|
||||||
|
void threadFunc();
|
||||||
|
void procClient(PIHTTPClient * c);
|
||||||
|
|
||||||
|
PIProtectedVariable<PIQueue<PIHTTPClient *>> clients;
|
||||||
|
PISemaphore sem;
|
||||||
|
PIVector<PIThread *> threads;
|
||||||
|
std::atomic_bool exiting = {false};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
210
libs/http_client/pihttpclient.cpp
Normal file
210
libs/http_client/pihttpclient.cpp
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
#include "pihttpclient.h"
|
||||||
|
|
||||||
|
#include "curl_thread_pool_p.h"
|
||||||
|
#include "piliterals_bytes.h"
|
||||||
|
#include "piliterals_string.h"
|
||||||
|
#include "pisystemtime.h"
|
||||||
|
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
|
|
||||||
|
int xfer_callback(void * ptr, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) {
|
||||||
|
return reinterpret_cast<PIHTTPClientBase *>(ptr)->__infoFunc(dltotal, dlnow, ultotal, ulnow);
|
||||||
|
}
|
||||||
|
|
||||||
|
int debug_callback(CURL * handle, curl_infotype type, char * data, size_t size, void * ptr) {
|
||||||
|
return reinterpret_cast<PIHTTPClientBase *>(ptr)->__debugFunc(type, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PRIVATE_DEFINITION_START(PIHTTPClient)
|
||||||
|
CURL * handle = nullptr;
|
||||||
|
PRIVATE_DEFINITION_END(PIHTTPClient)
|
||||||
|
|
||||||
|
|
||||||
|
PIHTTPClient::PIHTTPClient() {}
|
||||||
|
|
||||||
|
|
||||||
|
PIHTTPClient::~PIHTTPClient() {}
|
||||||
|
|
||||||
|
|
||||||
|
bool PIHTTPClient::init() {
|
||||||
|
if (is_cancel) return false;
|
||||||
|
PRIVATE->handle = curl_easy_init();
|
||||||
|
if (!PRIVATE->handle) return false;
|
||||||
|
curl_easy_setopt(PRIVATE->handle, CURLOPT_WRITEDATA, this);
|
||||||
|
curl_easy_setopt(PRIVATE->handle, CURLOPT_READDATA, this);
|
||||||
|
curl_easy_setopt(PRIVATE->handle, CURLOPT_XFERINFODATA, this);
|
||||||
|
curl_easy_setopt(PRIVATE->handle, CURLOPT_DEBUGDATA, this);
|
||||||
|
curl_easy_setopt(PRIVATE->handle, CURLOPT_HEADERDATA, this);
|
||||||
|
curl_easy_setopt(PRIVATE->handle, CURLOPT_WRITEFUNCTION, writeMemoryFunc);
|
||||||
|
curl_easy_setopt(PRIVATE->handle, CURLOPT_READFUNCTION, readMemoryFunc);
|
||||||
|
curl_easy_setopt(PRIVATE->handle, CURLOPT_XFERINFOFUNCTION, xfer_callback);
|
||||||
|
curl_easy_setopt(PRIVATE->handle, CURLOPT_DEBUGFUNCTION, debug_callback);
|
||||||
|
curl_easy_setopt(PRIVATE->handle, CURLOPT_HEADERFUNCTION, headerFunc);
|
||||||
|
curl_easy_setopt(PRIVATE->handle, CURLOPT_URL, url.dataUTF8());
|
||||||
|
curl_easy_setopt(PRIVATE->handle, CURLOPT_CUSTOMREQUEST, PIHTTP::methodName(request.method()));
|
||||||
|
curl_easy_setopt(PRIVATE->handle, CURLOPT_NOPROGRESS, 0L);
|
||||||
|
// curl_easy_setopt(PRIVATE->handle, CURLOPT_VERBOSE, 1L);
|
||||||
|
// curl_easy_setopt(PRIVATE->handle, CURLOPT_ERRORBUFFER, buffer_error.data());
|
||||||
|
curl_easy_setopt(PRIVATE->handle, CURLOPT_SSL_VERIFYPEER, 0L);
|
||||||
|
if (request.body().isNotEmpty()) {
|
||||||
|
curl_easy_setopt(PRIVATE->handle, CURLOPT_UPLOAD, 1L);
|
||||||
|
curl_easy_setopt(PRIVATE->handle, CURLOPT_INFILESIZE_LARGE, static_cast<curl_off_t>(request.body().size()));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIHTTPClient::perform() {
|
||||||
|
if (!PRIVATE->handle) return;
|
||||||
|
if (!is_cancel) {
|
||||||
|
// piCout << "perform ...";
|
||||||
|
PITimeMeasurer tm;
|
||||||
|
CURLcode res = curl_easy_perform(PRIVATE->handle);
|
||||||
|
// piCout << "done" << res << "in" << tm.elapsed_m() << ", bytes" << buffer_out.size();
|
||||||
|
if (res == CURLE_OK) {
|
||||||
|
reply.setBody(std::move(buffer_out));
|
||||||
|
if (on_finish) on_finish(reply);
|
||||||
|
} else {
|
||||||
|
if (res == CURLE_ABORTED_BY_CALLBACK || is_cancel) {
|
||||||
|
// piCerr << "curl_easy_perform() failed:" << curl_easy_strerror(res);
|
||||||
|
if (on_abort) on_abort(reply);
|
||||||
|
} else {
|
||||||
|
last_error = curl_easy_strerror(res);
|
||||||
|
if (on_error) on_error(reply);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// piCout << last_error;
|
||||||
|
curl_easy_cleanup(PRIVATE->handle);
|
||||||
|
PRIVATE->handle = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIHTTPClient::procHeaderLine(PIString & line) {
|
||||||
|
if (line.startsWith("HTTP"_a)) {
|
||||||
|
// HTTP/Версия КодСостояния Пояснение
|
||||||
|
line.cutLeft(5);
|
||||||
|
line.takeWord();
|
||||||
|
int code = line.takeWord().toInt();
|
||||||
|
// piCout << "code" << code;
|
||||||
|
reply.setCode(static_cast<PIHTTP::Code>(code));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int ind = line.find(':');
|
||||||
|
if (ind < 0) return;
|
||||||
|
PIString hname = line.takeLeft(ind);
|
||||||
|
line.cutLeft(1).trim();
|
||||||
|
reply.addHeader(hname, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t PIHTTPClient::writeMemoryFunc(void * contents, size_t size, size_t nmemb, void * ptr) {
|
||||||
|
size_t bytes = size * nmemb;
|
||||||
|
piCout << "writeMemoryFunc" << bytes;
|
||||||
|
auto client = reinterpret_cast<PIHTTPClient *>(ptr);
|
||||||
|
if (client->is_cancel) return CURL_WRITEFUNC_ERROR;
|
||||||
|
client->buffer_out.append(contents, bytes);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t PIHTTPClient::readMemoryFunc(void * contents, size_t size, size_t nmemb, void * ptr) {
|
||||||
|
size_t bytes = size * nmemb;
|
||||||
|
piCout << "readMemoryFunc" << bytes;
|
||||||
|
auto client = reinterpret_cast<PIHTTPClient *>(ptr);
|
||||||
|
if (client->is_cancel) return CURL_READFUNC_ABORT;
|
||||||
|
const auto & buffer(client->request.body());
|
||||||
|
if (buffer.isEmpty()) return 0;
|
||||||
|
// piCout << bytes;
|
||||||
|
ssize_t ret = piClamp<ssize_t>(bytes, 0, buffer.size_s() - client->read_pos);
|
||||||
|
if (ret < 0) ret = 0;
|
||||||
|
if (ret > 0) memcpy(contents, buffer.data(client->read_pos), ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t PIHTTPClient::headerFunc(char * contents, size_t size, size_t nmemb, void * ptr) {
|
||||||
|
size_t bytes = size * nmemb;
|
||||||
|
auto client = reinterpret_cast<PIHTTPClient *>(ptr);
|
||||||
|
if (client->is_cancel) return CURL_WRITEFUNC_ERROR;
|
||||||
|
PIString line = PIString::fromUTF8(contents, bytes).trim();
|
||||||
|
if (line.isNotEmpty()) client->procHeaderLine(line);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PIHTTPClient::infoFunc(ssize_t dltotal, ssize_t dlnow, ssize_t ultotal, ssize_t ulnow) {
|
||||||
|
// piCout << "infoFunc" << dltotal << dlnow << ultotal << ulnow;
|
||||||
|
if (is_cancel) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PIHTTPClient::debugFunc(int type, char * data, size_t size) {
|
||||||
|
// piCout << "debugFunc" << type << PIString::fromUTF8(data, size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIHTTPClient * PIHTTPClient::create(const PIString & url_, PIHTTP::Method method, const PIHTTP::MessageConst & req) {
|
||||||
|
PIHTTPClient * ret = new PIHTTPClient();
|
||||||
|
static_cast<PIHTTP::MessageConst &>(ret->request) = req;
|
||||||
|
ret->request.setMethod(method);
|
||||||
|
ret->url = url_;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIHTTPClient * PIHTTPClient::onFinish(std::function<void()> f) {
|
||||||
|
return onFinish([f](const PIHTTP::MessageConst &) { f(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIHTTPClient * PIHTTPClient::onFinish(std::function<void(const PIHTTP::MessageConst &)> f) {
|
||||||
|
on_finish = f;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIHTTPClient * PIHTTPClient::onError(std::function<void()> f) {
|
||||||
|
return onError([f](const PIHTTP::MessageConst &) { f(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIHTTPClient * PIHTTPClient::onError(std::function<void(const PIHTTP::MessageConst &)> f) {
|
||||||
|
on_error = f;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIHTTPClient * PIHTTPClient::onAbort(std::function<void()> f) {
|
||||||
|
return onAbort([f](const PIHTTP::MessageConst &) { f(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIHTTPClient * PIHTTPClient::onAbort(std::function<void(const PIHTTP::MessageConst &)> f) {
|
||||||
|
on_abort = f;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIHTTPClient::start() {
|
||||||
|
CurlThreadPool::instance()->registerClient(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PIHTTPClient::abort() {
|
||||||
|
is_cancel = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PIHTTPClientBase::__infoFunc(ssize_t dltotal, ssize_t dlnow, ssize_t ultotal, ssize_t ulnow) {
|
||||||
|
return reinterpret_cast<PIHTTPClient *>(this)->infoFunc(dltotal, dlnow, ultotal, ulnow);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int PIHTTPClientBase::__debugFunc(int type, char * data, size_t size) {
|
||||||
|
return reinterpret_cast<PIHTTPClient *>(this)->debugFunc(type, data, size);
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "microhttpd_server.h"
|
#include "microhttpd_server.h"
|
||||||
|
#include "piliterals_bytes.h"
|
||||||
#include "piliterals_string.h"
|
#include "piliterals_string.h"
|
||||||
#include "piliterals_time.h"
|
#include "piliterals_time.h"
|
||||||
|
|
||||||
@@ -31,11 +32,11 @@
|
|||||||
|
|
||||||
struct MicrohttpdServerConnection {
|
struct MicrohttpdServerConnection {
|
||||||
bool ready();
|
bool ready();
|
||||||
int send_reply(const MicrohttpdServer::Reply & r);
|
int sendReply(const PIHTTP::MessageMutable & r);
|
||||||
int send_error();
|
int sendError();
|
||||||
|
|
||||||
bool done = false;
|
bool done = false;
|
||||||
MicrohttpdServer::Method method = MicrohttpdServer::Method::Unknown;
|
PIHTTP::Method method = PIHTTP::Method::Unknown;
|
||||||
PIString path;
|
PIString path;
|
||||||
PIByteArray body;
|
PIByteArray body;
|
||||||
PIMap<PIString, PIString> headers, args, post;
|
PIMap<PIString, PIString> headers, args, post;
|
||||||
@@ -49,47 +50,48 @@ bool MicrohttpdServerConnection::ready() {
|
|||||||
if (!server) return false;
|
if (!server) return false;
|
||||||
if (done) return true;
|
if (done) return true;
|
||||||
done = true;
|
done = true;
|
||||||
MicrohttpdServer::Reply rep;
|
PIHTTP::MessageMutable rep;
|
||||||
if (method == MicrohttpdServer::Method::Get) {
|
if (method == PIHTTP::Method::Get) {
|
||||||
if (path == "/favicon.ico"_a) {
|
if (path == "/favicon.ico"_a) {
|
||||||
// piCout << "send favicon" << server->favicon.size() << "bytes";
|
// piCout << "send favicon" << server->favicon.size() << "bytes";
|
||||||
rep.setBody(server->favicon);
|
rep.setBody(server->favicon);
|
||||||
send_reply(rep);
|
sendReply(rep);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// piCout << "ready" << (int)method << path;
|
// piCout << "ready" << (int)method << path;
|
||||||
MicrohttpdServer::Request req;
|
PIHTTP::MessageMutable req;
|
||||||
req.method = method;
|
req.setMethod(method);
|
||||||
req.path = path;
|
req.setPath(path);
|
||||||
req.body = body;
|
req.setBody(body);
|
||||||
req.headers = headers;
|
req.headers() = headers;
|
||||||
req.args = args;
|
req.arguments() = args;
|
||||||
rep.setCode(MHD_HTTP_BAD_REQUEST);
|
rep.setCode(PIHTTP::Code::BadRequest);
|
||||||
if (server->callback) rep = server->callback(req);
|
if (server->callback) rep = server->callback(req);
|
||||||
rep.addFixedHeaders();
|
MicrohttpdServer::addFixedHeaders(rep);
|
||||||
send_reply(rep);
|
sendReply(rep);
|
||||||
|
// piCout << "ready ok" << (int)rep.code() << rep.body().size();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int MicrohttpdServerConnection::send_reply(const MicrohttpdServer::Reply & r) {
|
int MicrohttpdServerConnection::sendReply(const PIHTTP::MessageMutable & r) {
|
||||||
MHD_Response * response = MHD_create_response_from_buffer(r.body.size(), (void *)r.body.data(), MHD_RESPMEM_MUST_COPY);
|
MHD_Response * response = MHD_create_response_from_buffer(r.body().size(), (void *)r.body().data(), MHD_RESPMEM_MUST_COPY);
|
||||||
if (!response) {
|
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;
|
return MHD_NO;
|
||||||
}
|
}
|
||||||
auto it = r.headers.makeIterator();
|
auto it = r.headers().makeIterator();
|
||||||
while (it.next())
|
while (it.next())
|
||||||
MHD_add_response_header(response, it.key().dataAscii(), it.value().dataUTF8());
|
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);
|
int ret = MHD_queue_response(connection, static_cast<int>(r.code()), response);
|
||||||
MHD_destroy_response(response);
|
MHD_destroy_response(response);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int MicrohttpdServerConnection::send_error() {
|
int MicrohttpdServerConnection::sendError() {
|
||||||
return MHD_queue_response(connection, MHD_HTTP_BAD_REQUEST, MHD_create_response_from_buffer(0, nullptr, MHD_RESPMEM_MUST_COPY));
|
return MHD_queue_response(connection, MHD_HTTP_BAD_REQUEST, MHD_create_response_from_buffer(0, nullptr, MHD_RESPMEM_MUST_COPY));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,9 +100,9 @@ void log_callback(void * cls, const char * fmt, va_list ap) {
|
|||||||
MicrohttpdServer * server = (MicrohttpdServer *)cls;
|
MicrohttpdServer * server = (MicrohttpdServer *)cls;
|
||||||
piCout << "log" << server;
|
piCout << "log" << server;
|
||||||
if (!server) return;
|
if (!server) return;
|
||||||
char buffer[1024];
|
char buffer[1_KiB];
|
||||||
memset(buffer, 0, 1024);
|
memset(buffer, 0, 1_KiB);
|
||||||
std::vsnprintf(buffer, 1024, fmt, ap);
|
std::vsnprintf(buffer, 1_KiB, fmt, ap);
|
||||||
piCout << buffer;
|
piCout << buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,30 +160,30 @@ int answer_to_connection(void * cls,
|
|||||||
const char * upload_data,
|
const char * upload_data,
|
||||||
size_t * upload_data_size,
|
size_t * upload_data_size,
|
||||||
void ** con_cls) {
|
void ** con_cls) {
|
||||||
MicrohttpdServer * server = (MicrohttpdServer *)cls;
|
MicrohttpdServer * server = (MicrohttpdServer *)cls;
|
||||||
|
|
||||||
MicrohttpdServer::Method m = MicrohttpdServer::Method::Unknown;
|
PIHTTP::Method m = PIHTTP::Method::Unknown;
|
||||||
|
|
||||||
if (0 == strcmp(method, "GET"))
|
if (0 == strcmp(method, "GET"))
|
||||||
m = MicrohttpdServer::Method::Get;
|
m = PIHTTP::Method::Get;
|
||||||
else if (0 == strcmp(method, "POST"))
|
else if (0 == strcmp(method, "POST"))
|
||||||
m = MicrohttpdServer::Method::Post;
|
m = PIHTTP::Method::Post;
|
||||||
else if (0 == strcmp(method, "HEAD"))
|
else if (0 == strcmp(method, "HEAD"))
|
||||||
m = MicrohttpdServer::Method::Head;
|
m = PIHTTP::Method::Head;
|
||||||
else if (0 == strcmp(method, "PUT"))
|
else if (0 == strcmp(method, "PUT"))
|
||||||
m = MicrohttpdServer::Method::Put;
|
m = PIHTTP::Method::Put;
|
||||||
else if (0 == strcmp(method, "DELETE"))
|
else if (0 == strcmp(method, "DELETE"))
|
||||||
m = MicrohttpdServer::Method::Delete;
|
m = PIHTTP::Method::Delete;
|
||||||
else if (0 == strcmp(method, "CONNECT"))
|
else if (0 == strcmp(method, "CONNECT"))
|
||||||
m = MicrohttpdServer::Method::Connect;
|
m = PIHTTP::Method::Connect;
|
||||||
else if (0 == strcmp(method, "OPTIONS"))
|
else if (0 == strcmp(method, "OPTIONS"))
|
||||||
m = MicrohttpdServer::Method::Options;
|
m = PIHTTP::Method::Options;
|
||||||
else if (0 == strcmp(method, "TRACE"))
|
else if (0 == strcmp(method, "TRACE"))
|
||||||
m = MicrohttpdServer::Method::Trace;
|
m = PIHTTP::Method::Trace;
|
||||||
else if (0 == strcmp(method, "PATCH"))
|
else if (0 == strcmp(method, "PATCH"))
|
||||||
m = MicrohttpdServer::Method::Patch;
|
m = PIHTTP::Method::Patch;
|
||||||
|
|
||||||
if (m == MicrohttpdServer::Method::Unknown) {
|
if (m == PIHTTP::Method::Unknown) {
|
||||||
piCout << "[MicrohttpdServer]"
|
piCout << "[MicrohttpdServer]"
|
||||||
<< "Warning:"
|
<< "Warning:"
|
||||||
<< "Unknown method!";
|
<< "Unknown method!";
|
||||||
@@ -201,20 +203,20 @@ int answer_to_connection(void * cls,
|
|||||||
return MHD_YES;
|
return MHD_YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m == MicrohttpdServer::Method::Unknown) {
|
if (m == PIHTTP::Method::Unknown) {
|
||||||
return conn->send_error();
|
return conn->sendError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*upload_data_size) {
|
if (*upload_data_size) {
|
||||||
if (!conn->postprocessor) {
|
if (!conn->postprocessor) {
|
||||||
conn->postprocessor = MHD_create_post_processor(connection, 65536, (MHD_PostDataIterator)iterate_post, (void *)conn);
|
conn->postprocessor = MHD_create_post_processor(connection, 64_KiB, (MHD_PostDataIterator)iterate_post, (void *)conn);
|
||||||
}
|
}
|
||||||
conn->body.append(upload_data, *upload_data_size);
|
conn->body.append(upload_data, *upload_data_size);
|
||||||
MHD_post_process(conn->postprocessor, upload_data, *upload_data_size);
|
MHD_post_process(conn->postprocessor, upload_data, *upload_data_size);
|
||||||
*upload_data_size = 0;
|
*upload_data_size = 0;
|
||||||
} else {
|
} else {
|
||||||
// qDebug() << "answer ok";
|
// qDebug() << "answer ok";
|
||||||
if (!conn->ready()) return conn->send_error();
|
if (!conn->ready()) return conn->sendError();
|
||||||
}
|
}
|
||||||
return MHD_YES;
|
return MHD_YES;
|
||||||
}
|
}
|
||||||
@@ -305,34 +307,14 @@ void MicrohttpdServer::stop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void MicrohttpdServer::Reply::addHeader(const PIString & header, const PIString & value) {
|
void MicrohttpdServer::addFixedHeaders(PIHTTP::MessageMutable & msg) {
|
||||||
headers[header] = value;
|
if (!msg.headers().contains(PIHTTP::Header::ContentType)) {
|
||||||
}
|
if (msg.body().isNotEmpty()) {
|
||||||
|
if (msg.body().startsWith(PIByteArray::fromAscii("<!DOCTYPE html>")))
|
||||||
|
msg.addHeader(PIHTTP::Header::ContentType, "text/html; charset=utf-8");
|
||||||
void MicrohttpdServer::Reply::removeHeader(const PIString & header) {
|
else if (msg.body()[0] == '[' || msg.body()[0] == '{')
|
||||||
headers.remove(header);
|
msg.addHeader(PIHTTP::Header::ContentType, "application/json; charset=utf-8");
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MicrohttpdServer::Reply::setBody(const PIByteArray & b) {
|
|
||||||
body = b;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MicrohttpdServer::Reply::setCode(int c) {
|
|
||||||
code = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void MicrohttpdServer::Reply::addFixedHeaders() {
|
|
||||||
if (!headers.contains(MHD_HTTP_HEADER_CONTENT_TYPE)) {
|
|
||||||
if (body.isNotEmpty()) {
|
|
||||||
if (body.startsWith(PIByteArray::fromAscii("<!DOCTYPE html>")))
|
|
||||||
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, "*");
|
msg.addHeader(PIHTTP::Header::AccessControlAllowOrigin, "*");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,29 +4,29 @@
|
|||||||
|
|
||||||
|
|
||||||
PIHTTPServer::PIHTTPServer() {
|
PIHTTPServer::PIHTTPServer() {
|
||||||
setRequestCallback([this](const MicrohttpdServer::Request & r) -> MicrohttpdServer::Reply {
|
setRequestCallback([this](const PIHTTP::MessageConst & r) -> PIHTTP::MessageMutable {
|
||||||
MicrohttpdServer::Reply rep;
|
PIHTTP::MessageMutable reply;
|
||||||
rep.setCode(404);
|
reply.setCode(PIHTTP::Code::NotFound);
|
||||||
auto in_path = r.path.split("/");
|
auto in_path = r.path().split("/");
|
||||||
in_path.removeAll("");
|
in_path.removeAll("");
|
||||||
auto it = functions.makeReverseIterator();
|
auto it = functions.makeReverseIterator();
|
||||||
bool found = false;
|
bool found = false;
|
||||||
while (it.next()) {
|
while (it.next()) {
|
||||||
if (it.value().function) {
|
if (it.value().function) {
|
||||||
if (it.value().method == r.method) {
|
if (it.value().method == r.method()) {
|
||||||
if (it.value().match(in_path)) {
|
if (it.value().match(in_path)) {
|
||||||
rep = it.value().function(r);
|
reply = it.value().function(r);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found && unhandled) rep = unhandled(r);
|
if (!found && unhandled) reply = unhandled(r);
|
||||||
auto hit = reply_headers.makeIterator();
|
auto hit = reply_headers.makeIterator();
|
||||||
while (hit.next())
|
while (hit.next())
|
||||||
rep.addHeader(hit.key(), hit.value());
|
reply.addHeader(hit.key(), hit.value());
|
||||||
return rep;
|
return reply;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,8 +36,8 @@ PIHTTPServer::~PIHTTPServer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIHTTPServer::registerPath(const PIString & path, Method method, RequestFunction functor) {
|
void PIHTTPServer::registerPath(const PIString & path, PIHTTP::Method method, RequestFunction functor) {
|
||||||
auto & ep(functions[path + PIString::fromNumber((int)method)]);
|
auto & ep(functions[path + PIString::fromNumber(static_cast<int>(method))]);
|
||||||
ep.path = path.split("/");
|
ep.path = path.split("/");
|
||||||
ep.method = method;
|
ep.method = method;
|
||||||
ep.function = functor;
|
ep.function = functor;
|
||||||
@@ -50,7 +50,7 @@ void PIHTTPServer::registerUnhandled(RequestFunction functor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIHTTPServer::unregisterPath(const PIString & path, Method method) {
|
void PIHTTPServer::unregisterPath(const PIString & path, PIHTTP::Method method) {
|
||||||
auto pl = path.split("/");
|
auto pl = path.split("/");
|
||||||
pl.removeAll("");
|
pl.removeAll("");
|
||||||
auto it = functions.makeIterator();
|
auto it = functions.makeIterator();
|
||||||
|
|||||||
@@ -2679,7 +2679,7 @@ private:
|
|||||||
fprintf(stderr, "error with PIDeque<%s>::alloc\n", __PIP_TYPENAME__(T));
|
fprintf(stderr, "error with PIDeque<%s>::alloc\n", __PIP_TYPENAME__(T));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
assert(p_d);
|
assert(new_data);
|
||||||
pid_data = new_data;
|
pid_data = new_data;
|
||||||
pid_rsize = new_rsize;
|
pid_rsize = new_rsize;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2556,7 +2556,7 @@ private:
|
|||||||
fprintf(stderr, "error with PIVector<%s>::alloc\n", __PIP_TYPENAME__(T));
|
fprintf(stderr, "error with PIVector<%s>::alloc\n", __PIP_TYPENAME__(T));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
assert(p_d);
|
assert(new_data);
|
||||||
piv_data = new_data;
|
piv_data = new_data;
|
||||||
piv_rsize = new_rsize;
|
piv_rsize = new_rsize;
|
||||||
}
|
}
|
||||||
|
|||||||
61
libs/main/http_client/pihttpclient.h
Normal file
61
libs/main/http_client/pihttpclient.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
#ifndef pihttpclient_h
|
||||||
|
#define pihttpclient_h
|
||||||
|
|
||||||
|
#include "pihttptypes.h"
|
||||||
|
#include "pip_http_client_export.h"
|
||||||
|
|
||||||
|
|
||||||
|
class PIHTTPClientBase {
|
||||||
|
public:
|
||||||
|
int __infoFunc(ssize_t dltotal, ssize_t dlnow, ssize_t ultotal, ssize_t ulnow);
|
||||||
|
int __debugFunc(int type, char * data, size_t size);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PIP_HTTP_CLIENT_EXPORT PIHTTPClient: private PIHTTPClientBase {
|
||||||
|
friend class PIHTTPClientBase;
|
||||||
|
friend class CurlThreadPool;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static PIHTTPClient * create(const PIString & url, PIHTTP::Method method = PIHTTP::Method::Get, const PIHTTP::MessageConst & req = {});
|
||||||
|
|
||||||
|
PIHTTPClient * onFinish(std::function<void()> f);
|
||||||
|
PIHTTPClient * onFinish(std::function<void(const PIHTTP::MessageConst &)> f);
|
||||||
|
PIHTTPClient * onError(std::function<void()> f);
|
||||||
|
PIHTTPClient * onError(std::function<void(const PIHTTP::MessageConst &)> f);
|
||||||
|
PIHTTPClient * onAbort(std::function<void()> f);
|
||||||
|
PIHTTPClient * onAbort(std::function<void(const PIHTTP::MessageConst &)> f);
|
||||||
|
|
||||||
|
void start();
|
||||||
|
void abort();
|
||||||
|
|
||||||
|
PIString lastError() const { return last_error; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
NO_COPY_CLASS(PIHTTPClient)
|
||||||
|
PIHTTPClient();
|
||||||
|
virtual ~PIHTTPClient();
|
||||||
|
|
||||||
|
PRIVATE_DECLARATION(PIP_HTTP_CLIENT_EXPORT)
|
||||||
|
|
||||||
|
bool init();
|
||||||
|
void perform();
|
||||||
|
void procHeaderLine(PIString & line);
|
||||||
|
|
||||||
|
static size_t writeMemoryFunc(void * contents, size_t size, size_t nmemb, void * ptr);
|
||||||
|
static size_t readMemoryFunc(void * contents, size_t size, size_t nmemb, void * ptr);
|
||||||
|
static size_t headerFunc(char * contents, size_t size, size_t nmemb, void * ptr);
|
||||||
|
int infoFunc(ssize_t dltotal, ssize_t dlnow, ssize_t ultotal, ssize_t ulnow);
|
||||||
|
int debugFunc(int type, char * data, size_t size);
|
||||||
|
|
||||||
|
PIString url;
|
||||||
|
PIString last_error;
|
||||||
|
PIByteArray buffer_out;
|
||||||
|
PIHTTP::MessageMutable request, reply;
|
||||||
|
std::atomic_bool is_cancel = {false};
|
||||||
|
ssize_t read_pos = 0;
|
||||||
|
std::function<void(const PIHTTP::MessageConst &)> on_finish, on_error, on_abort;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
54
libs/main/http_client/pihttpclientmodule.h
Normal file
54
libs/main/http_client/pihttpclientmodule.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
PIP - Platform Independent Primitives
|
||||||
|
Module includes
|
||||||
|
Ivan Pelipenko peri4ko@yandex.ru, Andrey Bychkov work.a.b@yandex.ru
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
//! \defgroup HTTPServer HTTPServer
|
||||||
|
//! \~\brief
|
||||||
|
//! \~english HTTP client
|
||||||
|
//! \~russian HTTP сервер
|
||||||
|
//!
|
||||||
|
//! \~\details
|
||||||
|
//! \~english \section cmake_module_HTTPServer Building with CMake
|
||||||
|
//! \~russian \section cmake_module_HTTPServer Сборка с использованием CMake
|
||||||
|
//!
|
||||||
|
//! \~\code
|
||||||
|
//! find_package(PIP REQUIRED)
|
||||||
|
//! target_link_libraries([target] PIP::HTTPServer)
|
||||||
|
//! \endcode
|
||||||
|
//!
|
||||||
|
//! \~english \par Common
|
||||||
|
//! \~russian \par Общее
|
||||||
|
//!
|
||||||
|
//! \~english
|
||||||
|
//! These files provides HTTP server based on libmicrohttpd
|
||||||
|
//!
|
||||||
|
//! \~russian
|
||||||
|
//! Эти файлы обеспечивают HTTP сервер, основанный на libmicrohttpd
|
||||||
|
//!
|
||||||
|
//! \~\authors
|
||||||
|
//! \~english
|
||||||
|
//! Ivan Pelipenko peri4ko@yandex.ru;
|
||||||
|
//! \~russian
|
||||||
|
//! Иван Пелипенко peri4ko@yandex.ru;
|
||||||
|
//!
|
||||||
|
|
||||||
|
#ifndef pihttpclientmodule_H
|
||||||
|
#define pihttpclientmodule_H
|
||||||
|
|
||||||
|
#include "pihttpclient.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
328
libs/main/http_common/pihttpconstants.h
Normal file
328
libs/main/http_common/pihttpconstants.h
Normal file
@@ -0,0 +1,328 @@
|
|||||||
|
#ifndef pihttpconstants_h
|
||||||
|
#define pihttpconstants_h
|
||||||
|
|
||||||
|
|
||||||
|
namespace PIHTTP {
|
||||||
|
|
||||||
|
enum class Method {
|
||||||
|
Unknown,
|
||||||
|
Get,
|
||||||
|
Head,
|
||||||
|
Post,
|
||||||
|
Put,
|
||||||
|
Delete,
|
||||||
|
Connect,
|
||||||
|
Options,
|
||||||
|
Trace,
|
||||||
|
Patch
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Code {
|
||||||
|
Unknown,
|
||||||
|
Continue = 100,
|
||||||
|
SwitchingProtocols = 101,
|
||||||
|
Processing = 102,
|
||||||
|
EarlyHints = 103,
|
||||||
|
|
||||||
|
Ok = 200,
|
||||||
|
Created = 201,
|
||||||
|
Accepted = 202,
|
||||||
|
NonAuthoritativeInformation = 203,
|
||||||
|
NoContent = 204,
|
||||||
|
ResetContent = 205,
|
||||||
|
PartialContent = 206,
|
||||||
|
MultiStatus = 207,
|
||||||
|
AlreadyReported = 208,
|
||||||
|
IMUsed = 226,
|
||||||
|
|
||||||
|
MultipleChoices = 300,
|
||||||
|
MovedPermanently = 301,
|
||||||
|
Found = 302,
|
||||||
|
SeeOther = 303,
|
||||||
|
NotModified = 304,
|
||||||
|
UseProxy = 305,
|
||||||
|
SwitchProxy = 306,
|
||||||
|
TemporaryRedirect = 307,
|
||||||
|
PermanentRedirect = 308,
|
||||||
|
|
||||||
|
BadRequest = 400,
|
||||||
|
Unauthorized = 401,
|
||||||
|
PaymentRequired = 402,
|
||||||
|
Forbidden = 403,
|
||||||
|
NotFound = 404,
|
||||||
|
MethodNotAllowed = 405,
|
||||||
|
NotAcceptable = 406,
|
||||||
|
ProxyAuthenticationRequired = 407,
|
||||||
|
RequestTimeout = 408,
|
||||||
|
Conflict = 409,
|
||||||
|
Gone = 410,
|
||||||
|
LengthRequired = 411,
|
||||||
|
PreconditionFailed = 412,
|
||||||
|
ContentTooLarge = 413,
|
||||||
|
UriTooLong = 414,
|
||||||
|
UnsupportedMediaType = 415,
|
||||||
|
RangeNotSatisfiable = 416,
|
||||||
|
ExpectationFailed = 417,
|
||||||
|
MisdirectedRequest = 421,
|
||||||
|
UnprocessableContent = 422,
|
||||||
|
Locked = 423,
|
||||||
|
FailedDependency = 424,
|
||||||
|
TooEarly = 425,
|
||||||
|
UpgradeRequired = 426,
|
||||||
|
PreconditionRequired = 428,
|
||||||
|
TooManyRequests = 429,
|
||||||
|
RequestHeaderFieldsTooLarge = 431,
|
||||||
|
RetryWith = 449,
|
||||||
|
BlockedByWindowsParentalControls = 450,
|
||||||
|
UnavailableForLegalReasons = 451,
|
||||||
|
|
||||||
|
InternalServerError = 500,
|
||||||
|
NotImplemented = 501,
|
||||||
|
BadGateway = 502,
|
||||||
|
ServiceUnavailable = 503,
|
||||||
|
GatewayTimeout = 504,
|
||||||
|
HttpVersionNotSupported = 505,
|
||||||
|
VariantAlsoNegotiates = 506,
|
||||||
|
InsufficientStorage = 507,
|
||||||
|
LoopDetected = 508,
|
||||||
|
NotExtended = 510,
|
||||||
|
BandwidthLimitExceeded = 509,
|
||||||
|
NetworkAuthenticationRequired = 511,
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace Header {
|
||||||
|
constexpr static char Accept[] = "Accept";
|
||||||
|
constexpr static char AcceptCharset[] = "Accept-Charset";
|
||||||
|
constexpr static char AcceptEncoding[] = "Accept-Encoding";
|
||||||
|
constexpr static char AcceptLanguage[] = "Accept-Language";
|
||||||
|
constexpr static char AcceptRanges[] = "Accept-Ranges";
|
||||||
|
constexpr static char Age[] = "Age";
|
||||||
|
constexpr static char Allow[] = "Allow";
|
||||||
|
constexpr static char AuthenticationInfo[] = "Authentication-Info";
|
||||||
|
constexpr static char Authorization[] = "Authorization";
|
||||||
|
constexpr static char CacheControl[] = "Cache-Control";
|
||||||
|
constexpr static char Close[] = "Close";
|
||||||
|
constexpr static char Connection[] = "Connection";
|
||||||
|
constexpr static char ContentEncoding[] = "Content-Encoding";
|
||||||
|
constexpr static char ContentLanguage[] = "Content-Language";
|
||||||
|
constexpr static char ContentLength[] = "Content-Length";
|
||||||
|
constexpr static char ContentLocation[] = "Content-Location";
|
||||||
|
constexpr static char ContentRange[] = "Content-Range";
|
||||||
|
constexpr static char ContentType[] = "Content-Type";
|
||||||
|
constexpr static char Date[] = "Date";
|
||||||
|
constexpr static char ETag[] = "ETag";
|
||||||
|
constexpr static char Expect[] = "Expect";
|
||||||
|
constexpr static char Expires[] = "Expires";
|
||||||
|
constexpr static char From[] = "From";
|
||||||
|
constexpr static char Host[] = "Host";
|
||||||
|
constexpr static char IfMatch[] = "If-Match";
|
||||||
|
constexpr static char IfModifiedSince[] = "If-Modified-Since";
|
||||||
|
constexpr static char IfNoneMatch[] = "If-None-Match";
|
||||||
|
constexpr static char IfRange[] = "If-Range";
|
||||||
|
constexpr static char IfUnmodifiedSince[] = "If-Unmodified-Since";
|
||||||
|
constexpr static char LastModified[] = "Last-Modified";
|
||||||
|
constexpr static char Location[] = "Location";
|
||||||
|
constexpr static char MaxForwards[] = "Max-Forwards";
|
||||||
|
constexpr static char MimeVersion[] = "MIME-Version";
|
||||||
|
constexpr static char Pragma[] = "Pragma";
|
||||||
|
constexpr static char ProxyAuthenticate[] = "Proxy-Authenticate";
|
||||||
|
constexpr static char ProxyAuthenticationInfo[] = "Proxy-Authentication-Info";
|
||||||
|
constexpr static char ProxyAuthorization[] = "Proxy-Authorization";
|
||||||
|
constexpr static char Range[] = "Range";
|
||||||
|
constexpr static char Referer[] = "Referer";
|
||||||
|
constexpr static char RetryAfter[] = "Retry-After";
|
||||||
|
constexpr static char Server[] = "Server";
|
||||||
|
constexpr static char TE[] = "TE";
|
||||||
|
constexpr static char Trailer[] = "Trailer";
|
||||||
|
constexpr static char TransferEncoding[] = "Transfer-Encoding";
|
||||||
|
constexpr static char Upgrade[] = "Upgrade";
|
||||||
|
constexpr static char UserAgent[] = "User-Agent";
|
||||||
|
constexpr static char Vary[] = "Vary";
|
||||||
|
constexpr static char Via[] = "Via";
|
||||||
|
constexpr static char WWWAuthenticate[] = "WWW-Authenticate";
|
||||||
|
constexpr static char Asterisk[] = "*";
|
||||||
|
constexpr static char AIM[] = "A-IM";
|
||||||
|
constexpr static char AcceptAdditions[] = "Accept-Additions";
|
||||||
|
constexpr static char AcceptCH[] = "Accept-CH";
|
||||||
|
constexpr static char AcceptDatetime[] = "Accept-Datetime";
|
||||||
|
constexpr static char AcceptFeatures[] = "Accept-Features";
|
||||||
|
constexpr static char AcceptPatch[] = "Accept-Patch";
|
||||||
|
constexpr static char AcceptPost[] = "Accept-Post";
|
||||||
|
constexpr static char AcceptSignature[] = "Accept-Signature";
|
||||||
|
constexpr static char AccessControlAllowCredentials[] = "Access-Control-Allow-Credentials";
|
||||||
|
constexpr static char AccessControlAllowHeaders[] = "Access-Control-Allow-Headers";
|
||||||
|
constexpr static char AccessControlAllowMethods[] = "Access-Control-Allow-Methods";
|
||||||
|
constexpr static char AccessControlAllowOrigin[] = "Access-Control-Allow-Origin";
|
||||||
|
constexpr static char AccessControlExposeHeaders[] = "Access-Control-Expose-Headers";
|
||||||
|
constexpr static char AccessControlMaxAge[] = "Access-Control-Max-Age";
|
||||||
|
constexpr static char AccessControlRequestHeaders[] = "Access-Control-Request-Headers";
|
||||||
|
constexpr static char AccessControlRequestMethod[] = "Access-Control-Request-Method";
|
||||||
|
constexpr static char ALPN[] = "ALPN";
|
||||||
|
constexpr static char AltSvc[] = "Alt-Svc";
|
||||||
|
constexpr static char AltUsed[] = "Alt-Used";
|
||||||
|
constexpr static char Alternates[] = "Alternates";
|
||||||
|
constexpr static char ApplyToRedirectRef[] = "Apply-To-Redirect-Ref";
|
||||||
|
constexpr static char AuthenticationControl[] = "Authentication-Control";
|
||||||
|
constexpr static char CacheStatus[] = "Cache-Status";
|
||||||
|
constexpr static char CalManagedID[] = "Cal-Managed-ID";
|
||||||
|
constexpr static char CalDAVTimezones[] = "CalDAV-Timezones";
|
||||||
|
constexpr static char CapsuleProtocol[] = "Capsule-Protocol";
|
||||||
|
constexpr static char CDNCacheControl[] = "CDN-Cache-Control";
|
||||||
|
constexpr static char CDNLoop[] = "CDN-Loop";
|
||||||
|
constexpr static char CertNotAfter[] = "Cert-Not-After";
|
||||||
|
constexpr static char CertNotBefore[] = "Cert-Not-Before";
|
||||||
|
constexpr static char ClearSiteData[] = "Clear-Site-Data";
|
||||||
|
constexpr static char ClientCert[] = "Client-Cert";
|
||||||
|
constexpr static char ClientCertChain[] = "Client-Cert-Chain";
|
||||||
|
constexpr static char ContentDigest[] = "Content-Digest";
|
||||||
|
constexpr static char ContentDisposition[] = "Content-Disposition";
|
||||||
|
constexpr static char ContentID[] = "Content-ID";
|
||||||
|
constexpr static char ContentSecurityPolicy[] = "Content-Security-Policy";
|
||||||
|
constexpr static char ContentSecurityPolicyReportOnly[] = "Content-Security-Policy-Report-Only";
|
||||||
|
constexpr static char Cookie[] = "Cookie";
|
||||||
|
constexpr static char CrossOriginEmbedderPolicy[] = "Cross-Origin-Embedder-Policy";
|
||||||
|
constexpr static char CrossOriginEmbedderPolicyReportOnly[] = "Cross-Origin-Embedder-Policy-Report-Only";
|
||||||
|
constexpr static char CrossOriginOpenerPolicy[] = "Cross-Origin-Opener-Policy";
|
||||||
|
constexpr static char CrossOriginOpenerPolicyReportOnly[] = "Cross-Origin-Opener-Policy-Report-Only";
|
||||||
|
constexpr static char CrossOriginResourcePolicy[] = "Cross-Origin-Resource-Policy";
|
||||||
|
constexpr static char DASL[] = "DASL";
|
||||||
|
constexpr static char DAV[] = "DAV";
|
||||||
|
constexpr static char DeltaBase[] = "Delta-Base";
|
||||||
|
constexpr static char Depth[] = "Depth";
|
||||||
|
constexpr static char Destination[] = "Destination";
|
||||||
|
constexpr static char DifferentialID[] = "Differential-ID";
|
||||||
|
constexpr static char DPoP[] = "DPoP";
|
||||||
|
constexpr static char DPoPNonce[] = "DPoP-Nonce";
|
||||||
|
constexpr static char EarlyData[] = "Early-Data";
|
||||||
|
constexpr static char ExpectCT[] = "Expect-CT";
|
||||||
|
constexpr static char Forwarded[] = "Forwarded";
|
||||||
|
constexpr static char Hobareg[] = "Hobareg";
|
||||||
|
constexpr static char If[] = "If";
|
||||||
|
constexpr static char IfScheduleTagMatch[] = "If-Schedule-Tag-Match";
|
||||||
|
constexpr static char IM[] = "IM";
|
||||||
|
constexpr static char IncludeReferredTokenBindingID[] = "Include-Referred-Token-Binding-ID";
|
||||||
|
constexpr static char KeepAlive[] = "Keep-Alive";
|
||||||
|
constexpr static char Label[] = "Label";
|
||||||
|
constexpr static char LastEventID[] = "Last-Event-ID";
|
||||||
|
constexpr static char Link[] = "Link";
|
||||||
|
constexpr static char LockToken[] = "Lock-Token";
|
||||||
|
constexpr static char MementoDatetime[] = "Memento-Datetime";
|
||||||
|
constexpr static char Meter[] = "Meter";
|
||||||
|
constexpr static char Negotiate[] = "Negotiate";
|
||||||
|
constexpr static char NEL[] = "NEL";
|
||||||
|
constexpr static char ODataEntityid[] = "OData-EntityId";
|
||||||
|
constexpr static char ODataIsolation[] = "OData-Isolation";
|
||||||
|
constexpr static char ODataMaxversion[] = "OData-MaxVersion";
|
||||||
|
constexpr static char ODataVersion[] = "OData-Version";
|
||||||
|
constexpr static char OptionalWWWAuthenticate[] = "Optional-WWW-Authenticate";
|
||||||
|
constexpr static char OrderingType[] = "Ordering-Type";
|
||||||
|
constexpr static char Origin[] = "Origin";
|
||||||
|
constexpr static char OriginAgentCluster[] = "Origin-Agent-Cluster";
|
||||||
|
constexpr static char OSCORE[] = "OSCORE";
|
||||||
|
constexpr static char OSLCCoreVersion[] = "OSLC-Core-Version";
|
||||||
|
constexpr static char Overwrite[] = "Overwrite";
|
||||||
|
constexpr static char PingFrom[] = "Ping-From";
|
||||||
|
constexpr static char PingTo[] = "Ping-To";
|
||||||
|
constexpr static char Position[] = "Position";
|
||||||
|
constexpr static char Prefer[] = "Prefer";
|
||||||
|
constexpr static char PreferenceApplied[] = "Preference-Applied";
|
||||||
|
constexpr static char Priority[] = "Priority";
|
||||||
|
constexpr static char ProxyStatus[] = "Proxy-Status";
|
||||||
|
constexpr static char PublicKeyPins[] = "Public-Key-Pins";
|
||||||
|
constexpr static char PublicKeyPinsReportOnly[] = "Public-Key-Pins-Report-Only";
|
||||||
|
constexpr static char RedirectRef[] = "Redirect-Ref";
|
||||||
|
constexpr static char Refresh[] = "Refresh";
|
||||||
|
constexpr static char ReplayNonce[] = "Replay-Nonce";
|
||||||
|
constexpr static char ReprDigest[] = "Repr-Digest";
|
||||||
|
constexpr static char ScheduleReply[] = "Schedule-Reply";
|
||||||
|
constexpr static char ScheduleTag[] = "Schedule-Tag";
|
||||||
|
constexpr static char SecPurpose[] = "Sec-Purpose";
|
||||||
|
constexpr static char SecTokenBinding[] = "Sec-Token-Binding";
|
||||||
|
constexpr static char SecWebsocketAccept[] = "Sec-WebSocket-Accept";
|
||||||
|
constexpr static char SecWebsocketExtensions[] = "Sec-WebSocket-Extensions";
|
||||||
|
constexpr static char SecWebsocketKey[] = "Sec-WebSocket-Key";
|
||||||
|
constexpr static char SecWebsocketProtocol[] = "Sec-WebSocket-Protocol";
|
||||||
|
constexpr static char SecWebsocketVersion[] = "Sec-WebSocket-Version";
|
||||||
|
constexpr static char ServerTiming[] = "Server-Timing";
|
||||||
|
constexpr static char SetCookie[] = "Set-Cookie";
|
||||||
|
constexpr static char Signature[] = "Signature";
|
||||||
|
constexpr static char SignatureInput[] = "Signature-Input";
|
||||||
|
constexpr static char SLUG[] = "SLUG";
|
||||||
|
constexpr static char Soapaction[] = "SoapAction";
|
||||||
|
constexpr static char StatusURI[] = "Status-URI";
|
||||||
|
constexpr static char StrictTransportSecurity[] = "Strict-Transport-Security";
|
||||||
|
constexpr static char Sunset[] = "Sunset";
|
||||||
|
constexpr static char SurrogateCapability[] = "Surrogate-Capability";
|
||||||
|
constexpr static char SurrogateControl[] = "Surrogate-Control";
|
||||||
|
constexpr static char TCN[] = "TCN";
|
||||||
|
constexpr static char Timeout[] = "Timeout";
|
||||||
|
constexpr static char Topic[] = "Topic";
|
||||||
|
constexpr static char Traceparent[] = "Traceparent";
|
||||||
|
constexpr static char Tracestate[] = "Tracestate";
|
||||||
|
constexpr static char TTL[] = "TTL";
|
||||||
|
constexpr static char Urgency[] = "Urgency";
|
||||||
|
constexpr static char VariantVary[] = "Variant-Vary";
|
||||||
|
constexpr static char WantContentDigest[] = "Want-Content-Digest";
|
||||||
|
constexpr static char WantReprDigest[] = "Want-Repr-Digest";
|
||||||
|
constexpr static char XContentTypeOptions[] = "X-Content-Type-Options";
|
||||||
|
constexpr static char XFrameOptions[] = "X-Frame-Options";
|
||||||
|
constexpr static char AmpCacheTransform[] = "AMP-Cache-Transform";
|
||||||
|
constexpr static char ConfigurationContext[] = "Configuration-Context";
|
||||||
|
constexpr static char EDIINTFeatures[] = "EDIINT-Features";
|
||||||
|
constexpr static char Isolation[] = "Isolation";
|
||||||
|
constexpr static char PermissionsPolicy[] = "Permissions-Policy";
|
||||||
|
constexpr static char RepeatabilityClientID[] = "Repeatability-Client-ID";
|
||||||
|
constexpr static char RepeatabilityFirstSent[] = "Repeatability-First-Sent";
|
||||||
|
constexpr static char RepeatabilityRequestID[] = "Repeatability-Request-ID";
|
||||||
|
constexpr static char RepeatabilityResult[] = "Repeatability-Result";
|
||||||
|
constexpr static char ReportingEndpoints[] = "Reporting-Endpoints";
|
||||||
|
constexpr static char SecGPC[] = "Sec-GPC";
|
||||||
|
constexpr static char TimingAllowOrigin[] = "Timing-Allow-Origin";
|
||||||
|
constexpr static char CPEPInfo[] = "C-PEP-Info";
|
||||||
|
constexpr static char ProtocolInfo[] = "Protocol-Info";
|
||||||
|
constexpr static char ProtocolQuery[] = "Protocol-Query";
|
||||||
|
constexpr static char AccessControl[] = "Access-Control";
|
||||||
|
constexpr static char CExt[] = "C-Ext";
|
||||||
|
constexpr static char CMan[] = "C-Man";
|
||||||
|
constexpr static char COpt[] = "C-Opt";
|
||||||
|
constexpr static char CPEP[] = "C-PEP";
|
||||||
|
constexpr static char ContentBase[] = "Content-Base";
|
||||||
|
constexpr static char ContentMD5[] = "Content-MD5";
|
||||||
|
constexpr static char ContentScriptType[] = "Content-Script-Type";
|
||||||
|
constexpr static char ContentStyleType[] = "Content-Style-Type";
|
||||||
|
constexpr static char ContentVersion[] = "Content-Version";
|
||||||
|
constexpr static char Cookie2[] = "Cookie2";
|
||||||
|
constexpr static char DefaultStyle[] = "Default-Style";
|
||||||
|
constexpr static char DerivedFrom[] = "Derived-From";
|
||||||
|
constexpr static char Digest[] = "Digest";
|
||||||
|
constexpr static char Ext[] = "Ext";
|
||||||
|
constexpr static char Getprofile[] = "GetProfile";
|
||||||
|
constexpr static char HTTP2Settings[] = "HTTP2-Settings";
|
||||||
|
constexpr static char Man[] = "Man";
|
||||||
|
constexpr static char MethodCheck[] = "Method-Check";
|
||||||
|
constexpr static char MethodCheckExpires[] = "Method-Check-Expires";
|
||||||
|
constexpr static char Opt[] = "Opt";
|
||||||
|
constexpr static char P3P[] = "P3P";
|
||||||
|
constexpr static char PEP[] = "PEP";
|
||||||
|
constexpr static char PepInfo[] = "Pep-Info";
|
||||||
|
constexpr static char PICSLabel[] = "PICS-Label";
|
||||||
|
constexpr static char Profileobject[] = "ProfileObject";
|
||||||
|
constexpr static char Protocol[] = "Protocol";
|
||||||
|
constexpr static char ProtocolRequest[] = "Protocol-Request";
|
||||||
|
constexpr static char ProxyFeatures[] = "Proxy-Features";
|
||||||
|
constexpr static char ProxyInstruction[] = "Proxy-Instruction";
|
||||||
|
constexpr static char Public[] = "Public";
|
||||||
|
constexpr static char RefererRoot[] = "Referer-Root";
|
||||||
|
constexpr static char Safe[] = "Safe";
|
||||||
|
constexpr static char SecurityScheme[] = "Security-Scheme";
|
||||||
|
constexpr static char SetCookie2[] = "Set-Cookie2";
|
||||||
|
constexpr static char Setprofile[] = "SetProfile";
|
||||||
|
constexpr static char URI[] = "URI";
|
||||||
|
constexpr static char WantDigest[] = "Want-Digest";
|
||||||
|
constexpr static char Warning[] = "Warning";
|
||||||
|
}; // namespace Header
|
||||||
|
|
||||||
|
}; // namespace PIHTTP
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
18
libs/main/http_common/pihttptypes.cpp
Normal file
18
libs/main/http_common/pihttptypes.cpp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#include "pihttptypes.h"
|
||||||
|
|
||||||
|
|
||||||
|
const char * PIHTTP::methodName(Method m) {
|
||||||
|
switch (m) {
|
||||||
|
case Method::Get: return "GET";
|
||||||
|
case Method::Head: return "HEAD";
|
||||||
|
case Method::Post: return "POST";
|
||||||
|
case Method::Put: return "PUT";
|
||||||
|
case Method::Delete: return "DELETE";
|
||||||
|
case Method::Connect: return "CONNECT";
|
||||||
|
case Method::Options: return "OPTIONS";
|
||||||
|
case Method::Trace: return "TRACE";
|
||||||
|
case Method::Patch: return "PATCH";
|
||||||
|
default: break;
|
||||||
|
};
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
52
libs/main/http_common/pihttptypes.h
Normal file
52
libs/main/http_common/pihttptypes.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#ifndef pihttptypes_h
|
||||||
|
#define pihttptypes_h
|
||||||
|
|
||||||
|
#include "pihttpconstants.h"
|
||||||
|
#include "pip_export.h"
|
||||||
|
#include "pistring.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace PIHTTP {
|
||||||
|
|
||||||
|
|
||||||
|
class PIP_EXPORT MessageConst {
|
||||||
|
public:
|
||||||
|
PIHTTP::Method method() const { return m_method; }
|
||||||
|
PIHTTP::Code code() const { return m_code; }
|
||||||
|
const PIString & path() const { return m_path; }
|
||||||
|
const PIByteArray & body() const { return m_body; }
|
||||||
|
const PIMap<PIString, PIString> & headers() const { return m_headers; }
|
||||||
|
const PIMap<PIString, PIString> & arguments() const { return m_arguments; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
PIHTTP::Method m_method = PIHTTP::Method::Unknown;
|
||||||
|
PIHTTP::Code m_code = PIHTTP::Code::Ok;
|
||||||
|
PIString m_path;
|
||||||
|
PIByteArray m_body;
|
||||||
|
PIMap<PIString, PIString> m_headers;
|
||||||
|
PIMap<PIString, PIString> m_arguments;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PIP_EXPORT MessageMutable: public MessageConst {
|
||||||
|
public:
|
||||||
|
void setMethod(PIHTTP::Method m) { m_method = m; }
|
||||||
|
void setCode(PIHTTP::Code c) { m_code = c; }
|
||||||
|
void setPath(PIString p) { m_path = std::move(p); }
|
||||||
|
void setBody(PIByteArray b) { m_body = std::move(b); }
|
||||||
|
const PIMap<PIString, PIString> & headers() const { return m_headers; }
|
||||||
|
const PIMap<PIString, PIString> & arguments() const { return m_arguments; }
|
||||||
|
PIMap<PIString, PIString> & headers() { return m_headers; }
|
||||||
|
PIMap<PIString, PIString> & arguments() { return m_arguments; }
|
||||||
|
void addHeader(const PIString & header, const PIString & value) { m_headers[header] = value; }
|
||||||
|
void removeHeader(const PIString & header) { m_headers.remove(header); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
PIP_EXPORT const char * methodName(Method m);
|
||||||
|
|
||||||
|
|
||||||
|
}; // namespace PIHTTP
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef MICROHTTPD_SERVER_P_H
|
#ifndef MICROHTTPD_SERVER_P_H
|
||||||
#define MICROHTTPD_SERVER_P_H
|
#define MICROHTTPD_SERVER_P_H
|
||||||
|
|
||||||
#include "pibase.h"
|
#include "pihttptypes.h"
|
||||||
#include "piobject.h"
|
#include "piobject.h"
|
||||||
#include "pip_http_server_export.h"
|
#include "pip_http_server_export.h"
|
||||||
|
|
||||||
@@ -15,18 +15,6 @@ public:
|
|||||||
MicrohttpdServer();
|
MicrohttpdServer();
|
||||||
virtual ~MicrohttpdServer();
|
virtual ~MicrohttpdServer();
|
||||||
|
|
||||||
enum class Method {
|
|
||||||
Unknown,
|
|
||||||
Get,
|
|
||||||
Head,
|
|
||||||
Post,
|
|
||||||
Put,
|
|
||||||
Delete,
|
|
||||||
Connect,
|
|
||||||
Options,
|
|
||||||
Trace,
|
|
||||||
Patch
|
|
||||||
};
|
|
||||||
enum class Option {
|
enum class Option {
|
||||||
ConnectionLimit, // uint
|
ConnectionLimit, // uint
|
||||||
ConnectionTimeout, // uint, sec
|
ConnectionTimeout, // uint, sec
|
||||||
@@ -36,30 +24,6 @@ public:
|
|||||||
HTTPSKeyPassword // const char * to passwd for key.pem
|
HTTPSKeyPassword // const char * to passwd for key.pem
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PIP_HTTP_SERVER_EXPORT Request {
|
|
||||||
MicrohttpdServer::Method method;
|
|
||||||
PIString path;
|
|
||||||
PIByteArray body;
|
|
||||||
PIMap<PIString, PIString> headers;
|
|
||||||
PIMap<PIString, PIString> args;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PIP_HTTP_SERVER_EXPORT Reply {
|
|
||||||
friend struct MicrohttpdServerConnection;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void addHeader(const PIString & header, const PIString & value);
|
|
||||||
void removeHeader(const PIString & header);
|
|
||||||
void setBody(const PIByteArray & b);
|
|
||||||
void setCode(int c);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void addFixedHeaders();
|
|
||||||
int code = 200;
|
|
||||||
PIByteArray body;
|
|
||||||
PIMap<PIString, PIString> headers;
|
|
||||||
};
|
|
||||||
|
|
||||||
void setOption(Option o, PIVariant v);
|
void setOption(Option o, PIVariant v);
|
||||||
void setFavicon(const PIByteArray & im);
|
void setFavicon(const PIByteArray & im);
|
||||||
|
|
||||||
@@ -68,14 +32,15 @@ public:
|
|||||||
bool isListen() const;
|
bool isListen() const;
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
void setRequestCallback(std::function<Reply(Request)> c) { callback = c; }
|
void setRequestCallback(std::function<PIHTTP::MessageMutable(const PIHTTP::MessageConst &)> c) { callback = c; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static void addFixedHeaders(PIHTTP::MessageMutable & msg);
|
||||||
PRIVATE_DECLARATION(PIP_HTTP_SERVER_EXPORT)
|
PRIVATE_DECLARATION(PIP_HTTP_SERVER_EXPORT)
|
||||||
|
|
||||||
PIByteArray favicon;
|
PIByteArray favicon;
|
||||||
PIMap<Option, PIVariant> opts;
|
PIMap<Option, PIVariant> opts;
|
||||||
std::function<Reply(Request)> callback;
|
std::function<PIHTTP::MessageMutable(const PIHTTP::MessageConst &)> callback;
|
||||||
PIByteArray mem_key, mem_cert, key_pass;
|
PIByteArray mem_key, mem_cert, key_pass;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ public:
|
|||||||
PIHTTPServer();
|
PIHTTPServer();
|
||||||
virtual ~PIHTTPServer();
|
virtual ~PIHTTPServer();
|
||||||
|
|
||||||
using RequestFunction = std::function<MicrohttpdServer::Reply(const MicrohttpdServer::Request &)>;
|
using RequestFunction = std::function<PIHTTP::MessageMutable(const PIHTTP::MessageConst &)>;
|
||||||
|
|
||||||
void registerPath(const PIString & path, MicrohttpdServer::Method method, RequestFunction functor);
|
void registerPath(const PIString & path, PIHTTP::Method method, RequestFunction functor);
|
||||||
void registerUnhandled(RequestFunction functor);
|
void registerUnhandled(RequestFunction functor);
|
||||||
void unregisterPath(const PIString & path, MicrohttpdServer::Method method);
|
void unregisterPath(const PIString & path, PIHTTP::Method method);
|
||||||
void unregisterPath(const PIString & path);
|
void unregisterPath(const PIString & path);
|
||||||
|
|
||||||
void addReplyHeader(const PIString & name, const PIString & value) { reply_headers[name] = value; }
|
void addReplyHeader(const PIString & name, const PIString & value) { reply_headers[name] = value; }
|
||||||
@@ -25,7 +25,7 @@ private:
|
|||||||
struct Endpoint {
|
struct Endpoint {
|
||||||
bool match(const PIStringList & in_path) const;
|
bool match(const PIStringList & in_path) const;
|
||||||
PIStringList path;
|
PIStringList path;
|
||||||
MicrohttpdServer::Method method = MicrohttpdServer::Method::Unknown;
|
PIHTTP::Method method = PIHTTP::Method::Unknown;
|
||||||
RequestFunction function;
|
RequestFunction function;
|
||||||
};
|
};
|
||||||
PIMap<PIString, PIString> reply_headers;
|
PIMap<PIString, PIString> reply_headers;
|
||||||
|
|||||||
41
main.cpp
41
main.cpp
@@ -1,8 +1,9 @@
|
|||||||
|
#include "pihttpclient.h"
|
||||||
#include "pip.h"
|
#include "pip.h"
|
||||||
|
|
||||||
using namespace PICoutManipulators;
|
using namespace PICoutManipulators;
|
||||||
|
|
||||||
PIKbdListener kbd;
|
// PIKbdListener kbd;
|
||||||
const char * pageTitle = "<!DOCTYPE html>"
|
const char * pageTitle = "<!DOCTYPE html>"
|
||||||
"<html>"
|
"<html>"
|
||||||
"<body>"
|
"<body>"
|
||||||
@@ -12,16 +13,50 @@ const char * pageTitle = "<!DOCTYPE html>"
|
|||||||
|
|
||||||
|
|
||||||
int main(int argc, char * argv[]) {
|
int main(int argc, char * argv[]) {
|
||||||
|
PIHTTPServer server;
|
||||||
|
server.listen({"127.0.0.1:7777"});
|
||||||
|
server.registerUnhandled([](const PIHTTP::MessageConst & msg) -> PIHTTP::MessageMutable {
|
||||||
|
PIHTTP::MessageMutable ret;
|
||||||
|
piCout << "server rec:\n\tpath: %1\n\tmethod: %2\n\tbody: %3"_a.arg(msg.path())
|
||||||
|
.arg((int)msg.method())
|
||||||
|
.arg(PIString::fromUTF8(msg.body()));
|
||||||
|
ret.setCode(PIHTTP::Code::BadRequest);
|
||||||
|
ret.setBody(PIByteArray::fromAscii("hello client! 0123456789"));
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
|
||||||
|
PIHTTP::MessageMutable req;
|
||||||
|
req.setBody(PIByteArray::fromAscii("hello server!"));
|
||||||
|
auto * c = PIHTTPClient::create("http://127.0.0.1:7777/api", PIHTTP::Method::Get, req);
|
||||||
|
c->onFinish([](PIHTTP::MessageConst r) {
|
||||||
|
piCout << "finish" << (int)r.code();
|
||||||
|
piCout << "headers" << r.headers();
|
||||||
|
piCout << "body" << PIString::fromUTF8(r.body());
|
||||||
|
})
|
||||||
|
->onError([c](PIHTTP::MessageConst r) {
|
||||||
|
piCout << "error" << (int)r.code();
|
||||||
|
piCout << "msg" << c->lastError();
|
||||||
|
})
|
||||||
|
->onAbort([c](PIHTTP::MessageConst r) {
|
||||||
|
piCout << "abort" << (int)r.code();
|
||||||
|
piCout << "msg" << c->lastError();
|
||||||
|
})
|
||||||
|
->start();
|
||||||
|
piMSleep(500);
|
||||||
|
server.stop();
|
||||||
|
// c->abort();
|
||||||
|
// piMSleep(500);
|
||||||
|
return 0;
|
||||||
// piCout << PIString::readableSize(PISystemMonitor::usedRAM());
|
// piCout << PIString::readableSize(PISystemMonitor::usedRAM());
|
||||||
|
|
||||||
PIVector<int> vi;
|
/*PIVector<int> vi;
|
||||||
piForTimes(10) {
|
piForTimes(10) {
|
||||||
piSleep(2.);
|
piSleep(2.);
|
||||||
vi.enlarge(1000000);
|
vi.enlarge(1000000);
|
||||||
piCout << "now" << vi.size() << vi.capacity();
|
piCout << "now" << vi.size() << vi.capacity();
|
||||||
}
|
}
|
||||||
|
|
||||||
piSleep(5.);
|
piSleep(5.);*/
|
||||||
/*kbd.enableExitCapture();
|
/*kbd.enableExitCapture();
|
||||||
|
|
||||||
PIHTTPServer server;
|
PIHTTPServer server;
|
||||||
|
|||||||
Reference in New Issue
Block a user