version 5.1.0
PIHTTPServer now can handle path with partially *, ** and {} path arguments
PIHTTP::MessageConst add queryArguments() and pathArguments(). arguments() now union of these args
This commit is contained in:
@@ -5,9 +5,9 @@ if (POLICY CMP0177)
|
|||||||
endif()
|
endif()
|
||||||
project(PIP)
|
project(PIP)
|
||||||
set(PIP_MAJOR 5)
|
set(PIP_MAJOR 5)
|
||||||
set(PIP_MINOR 0)
|
set(PIP_MINOR 1)
|
||||||
set(PIP_REVISION 0)
|
set(PIP_REVISION 0)
|
||||||
set(PIP_SUFFIX _beta)
|
set(PIP_SUFFIX )
|
||||||
set(PIP_COMPANY SHS)
|
set(PIP_COMPANY SHS)
|
||||||
set(PIP_DOMAIN org.SHS)
|
set(PIP_DOMAIN org.SHS)
|
||||||
|
|
||||||
|
|||||||
@@ -93,8 +93,8 @@ bool MicrohttpdServerConnection::ready() {
|
|||||||
req.setMethod(method);
|
req.setMethod(method);
|
||||||
req.setPath(path);
|
req.setPath(path);
|
||||||
req.setBody(body);
|
req.setBody(body);
|
||||||
req.headers() = headers;
|
req.headers() = headers;
|
||||||
req.arguments() = args;
|
req.queryArguments() = args;
|
||||||
rep.setCode(Code::BadRequest);
|
rep.setCode(Code::BadRequest);
|
||||||
if (server->callback) rep = server->callback(req);
|
if (server->callback) rep = server->callback(req);
|
||||||
MicrohttpdServer::addFixedHeaders(rep);
|
MicrohttpdServer::addFixedHeaders(rep);
|
||||||
@@ -150,14 +150,14 @@ void log_callback(void * cls, const char * fmt, va_list ap) {
|
|||||||
|
|
||||||
|
|
||||||
int iterate_post(void * conn_cls,
|
int iterate_post(void * conn_cls,
|
||||||
MHD_ValueKind kind,
|
MHD_ValueKind kind,
|
||||||
const char * key,
|
const char * key,
|
||||||
const char * filename,
|
const char * filename,
|
||||||
const char * content_type,
|
const char * content_type,
|
||||||
const char * transfer_encoding,
|
const char * transfer_encoding,
|
||||||
const char * data,
|
const char * data,
|
||||||
uint64_t off,
|
uint64_t off,
|
||||||
size_t size) {
|
size_t size) {
|
||||||
MicrohttpdServerConnection * conn = (MicrohttpdServerConnection *)conn_cls;
|
MicrohttpdServerConnection * conn = (MicrohttpdServerConnection *)conn_cls;
|
||||||
if (!conn) return MHD_NO;
|
if (!conn) return MHD_NO;
|
||||||
conn->post[PIString::fromUTF8(key)] = PIString::fromUTF8(data);
|
conn->post[PIString::fromUTF8(key)] = PIString::fromUTF8(data);
|
||||||
@@ -195,13 +195,13 @@ int args_iterate(void * cls, MHD_ValueKind kind, const char * key, const char *
|
|||||||
|
|
||||||
|
|
||||||
int answer_callback(void * cls,
|
int answer_callback(void * cls,
|
||||||
MHD_Connection * connection,
|
MHD_Connection * connection,
|
||||||
const char * url,
|
const char * url,
|
||||||
const char * method,
|
const char * method,
|
||||||
const char * version,
|
const char * version,
|
||||||
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;
|
||||||
|
|
||||||
Method m = Method::Unknown;
|
Method m = Method::Unknown;
|
||||||
|
|||||||
@@ -7,20 +7,25 @@ PIHTTPServer::PIHTTPServer() {
|
|||||||
setRequestCallback([this](const PIHTTP::MessageConst & r) -> PIHTTP::MessageMutable {
|
setRequestCallback([this](const PIHTTP::MessageConst & r) -> PIHTTP::MessageMutable {
|
||||||
PIHTTP::MessageMutable reply;
|
PIHTTP::MessageMutable reply;
|
||||||
reply.setCode(PIHTTP::Code::NotFound);
|
reply.setCode(PIHTTP::Code::NotFound);
|
||||||
auto in_path = r.path().split("/");
|
auto in_path = splitPath(r.path());
|
||||||
in_path.removeAll("");
|
auto it = endpoints.makeReverseIterator();
|
||||||
auto it = functions.makeReverseIterator();
|
bool found = false;
|
||||||
bool found = false;
|
|
||||||
while (it.next()) {
|
while (it.next()) {
|
||||||
if (it.value().function) {
|
for (const auto & ep: it.value()) {
|
||||||
if (it.value().method == r.method()) {
|
if (ep.function && ep.method == r.method()) {
|
||||||
if (it.value().match(in_path)) {
|
PIMap<PIString, PIString> ext_args;
|
||||||
reply = it.value().function(r);
|
if (ep.match(in_path, ext_args)) {
|
||||||
|
auto & r_mut(static_cast<PIHTTP::MessageMutable &>(const_cast<PIHTTP::MessageConst &>(r)));
|
||||||
|
r_mut.pathArguments() = ext_args;
|
||||||
|
r_mut.arguments() = r_mut.pathArguments();
|
||||||
|
r_mut.arguments() << r_mut.queryArguments();
|
||||||
|
reply = ep.function(r);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (found) break;
|
||||||
}
|
}
|
||||||
if (!found && unhandled) reply = unhandled(r);
|
if (!found && unhandled) reply = unhandled(r);
|
||||||
auto hit = reply_headers.makeIterator();
|
auto hit = reply_headers.makeIterator();
|
||||||
@@ -36,12 +41,13 @@ PIHTTPServer::~PIHTTPServer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIHTTPServer::registerPath(const PIString & path, PIHTTP::Method method, RequestFunction functor) {
|
bool PIHTTPServer::registerPath(const PIString & path, PIHTTP::Method method, RequestFunction functor) {
|
||||||
auto & ep(functions[path + PIString::fromNumber(static_cast<int>(method))]);
|
Endpoint ep;
|
||||||
ep.path = path.split("/");
|
if (!ep.create(path)) return false;
|
||||||
ep.method = method;
|
ep.method = method;
|
||||||
ep.function = functor;
|
ep.function = functor;
|
||||||
ep.path.removeAll("");
|
endpoints[ep.priority] << ep;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -51,40 +57,143 @@ void PIHTTPServer::registerUnhandled(RequestFunction functor) {
|
|||||||
|
|
||||||
|
|
||||||
void PIHTTPServer::unregisterPath(const PIString & path, PIHTTP::Method method) {
|
void PIHTTPServer::unregisterPath(const PIString & path, PIHTTP::Method method) {
|
||||||
auto pl = path.split("/");
|
auto pl = splitPath(path);
|
||||||
pl.removeAll("");
|
auto it = endpoints.makeIterator();
|
||||||
auto it = functions.makeIterator();
|
|
||||||
while (it.next()) {
|
while (it.next()) {
|
||||||
if (it.value().method == method) {
|
it.value().removeWhere([&pl, method](const Endpoint & ep) { return ep.path == pl && ep.method == method; });
|
||||||
if (it.value().path == pl) {
|
|
||||||
functions.remove(it.key());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
endpoints.removeWhere([](uint, const PIVector<Endpoint> & epl) { return epl.isEmpty(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PIHTTPServer::unregisterPath(const PIString & path) {
|
void PIHTTPServer::unregisterPath(const PIString & path) {
|
||||||
auto pl = path.split("/");
|
auto pl = splitPath(path);
|
||||||
pl.removeAll("");
|
auto it = endpoints.makeIterator();
|
||||||
auto it = functions.makeIterator();
|
|
||||||
PIStringList keys;
|
|
||||||
while (it.next()) {
|
while (it.next()) {
|
||||||
if (it.value().path == pl) {
|
it.value().removeWhere([&pl](const Endpoint & ep) { return ep.path == pl; });
|
||||||
keys << it.key();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for (const auto & k: keys)
|
endpoints.removeWhere([](uint, const PIVector<Endpoint> & epl) { return epl.isEmpty(); });
|
||||||
functions.remove(k);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PIHTTPServer::Endpoint::match(const PIStringList & in_path) const {
|
PIStringList PIHTTPServer::splitPath(const PIString & path) {
|
||||||
if (in_path.size() != path.size()) return false;
|
auto ret = path.split("/");
|
||||||
for (int i = 0; i < path.size_s(); ++i) {
|
ret.removeAll({});
|
||||||
if (path[i] == "*"_a) continue;
|
return ret;
|
||||||
if (path[i] != in_path[i]) return false;
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIHTTPServer::PathElement::PathElement(const PIString & reg) {
|
||||||
|
source = reg;
|
||||||
|
if (reg == "*"_a) {
|
||||||
|
type = Type::AnyOne;
|
||||||
|
} else if (reg == "**"_a) {
|
||||||
|
type = Type::AnyMany;
|
||||||
|
} else if (reg.contains('*')) {
|
||||||
|
type = Type::AnyPart;
|
||||||
|
parts = reg.split('*');
|
||||||
|
} else if (reg.contains('{')) {
|
||||||
|
type = Type::Arguments;
|
||||||
|
int ind = 0, eind = 0, pind = 0;
|
||||||
|
for (;;) {
|
||||||
|
ind = reg.find('{', ind);
|
||||||
|
if (ind < 0) break;
|
||||||
|
eind = reg.find('}', ind + 1);
|
||||||
|
if (eind < 0) break;
|
||||||
|
arguments.insert(arguments.size_s(), reg.mid(ind + 1, eind - ind - 1));
|
||||||
|
if (ind == 0)
|
||||||
|
parts << PIString();
|
||||||
|
else {
|
||||||
|
if (ind > pind)
|
||||||
|
parts << reg.mid(pind, ind - pind);
|
||||||
|
else if (parts.isNotEmpty()) {
|
||||||
|
piCout << "[PIHTTPServer] Warning: sequential arguments, ignoring this path!";
|
||||||
|
type = Type::Invalid;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ind = pind = eind + 1;
|
||||||
|
}
|
||||||
|
if (eind < reg.size_s() - 1) parts << reg.mid(eind + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PIHTTPServer::PathElement::match(const PIString & in, PIMap<PIString, PIString> & ext_args) const {
|
||||||
|
// piCout << "match" << source << "with" << in;
|
||||||
|
if (type == Type::AnyOne) return true;
|
||||||
|
if (type == Type::AnyPart) {
|
||||||
|
int ind = 0;
|
||||||
|
for (const auto & m: parts) {
|
||||||
|
ind = in.find(m, ind);
|
||||||
|
if (ind < 0) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (type == Type::Arguments) {
|
||||||
|
int ind = 0, eind = 0;
|
||||||
|
for (int i = 0; i < parts.size_s(); ++i) {
|
||||||
|
const auto & m(parts[i]);
|
||||||
|
if (m.isNotEmpty()) {
|
||||||
|
ind = in.find(m, eind);
|
||||||
|
if (ind < 0) return false;
|
||||||
|
}
|
||||||
|
if (i > 0) {
|
||||||
|
ext_args[arguments.value(i - 1)] = in.mid(eind, ind - eind);
|
||||||
|
}
|
||||||
|
eind = ind + m.size_s();
|
||||||
|
}
|
||||||
|
if (parts.size() == arguments.size()) {
|
||||||
|
ext_args[arguments.value(arguments.size_s() - 1)] = in.mid(eind);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return source == in;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint PIHTTPServer::PathElement::priority() const {
|
||||||
|
switch (type) {
|
||||||
|
case Type::Fixed: return 0x10000; break;
|
||||||
|
case Type::Arguments: return 0x1000; break;
|
||||||
|
case Type::AnyPart: return 0x100; break;
|
||||||
|
case Type::AnyOne: return 0x10; break;
|
||||||
|
case Type::AnyMany: return 0x1; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PIHTTPServer::Endpoint::create(const PIString & p) {
|
||||||
|
path = splitPath(p);
|
||||||
|
prepared_path.clear();
|
||||||
|
priority = 0;
|
||||||
|
for (const auto & i: path) {
|
||||||
|
PathElement pe(i);
|
||||||
|
prepared_path << pe;
|
||||||
|
path_types |= pe.type;
|
||||||
|
priority += pe.priority();
|
||||||
|
}
|
||||||
|
return !path_types[PathElement::Type::Invalid];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PIHTTPServer::Endpoint::match(const PIStringList & in_path, PIMap<PIString, PIString> & ext_args) const {
|
||||||
|
if (path_types[PathElement::Type::AnyMany]) {
|
||||||
|
int any_ind = path.indexOf("**"_a);
|
||||||
|
for (int i = 0; i < any_ind; ++i) {
|
||||||
|
if (!prepared_path[i].match(in_path[i], ext_args)) return false;
|
||||||
|
}
|
||||||
|
int si = prepared_path.size_s() - 1, ii = in_path.size_s() - 1;
|
||||||
|
for (; si > any_ind && ii >= 0; --si, --ii) {
|
||||||
|
if (!prepared_path[si].match(in_path[ii], ext_args)) return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (in_path.size() != prepared_path.size()) return false;
|
||||||
|
for (int i = 0; i < prepared_path.size_s(); ++i) {
|
||||||
|
if (!prepared_path[i].match(in_path[i], ext_args)) return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,14 +59,26 @@ PIHTTP::MessageMutable & PIHTTP::MessageMutable::removeHeader(const PIString & h
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIHTTP::MessageMutable & PIHTTP::MessageMutable::addArgument(const PIString & arg, const PIString & value) {
|
PIHTTP::MessageMutable & PIHTTP::MessageMutable::addQueryArgument(const PIString & arg, const PIString & value) {
|
||||||
m_arguments[arg] = value;
|
m_query_arguments[arg] = value;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PIHTTP::MessageMutable & PIHTTP::MessageMutable::removeArgument(const PIString & arg) {
|
PIHTTP::MessageMutable & PIHTTP::MessageMutable::removeQueryArgument(const PIString & arg) {
|
||||||
m_arguments.remove(arg);
|
m_query_arguments.remove(arg);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIHTTP::MessageMutable & PIHTTP::MessageMutable::addPathArgument(const PIString & arg, const PIString & value) {
|
||||||
|
m_path_arguments[arg] = value;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PIHTTP::MessageMutable & PIHTTP::MessageMutable::removePathArgument(const PIString & arg) {
|
||||||
|
m_path_arguments.remove(arg);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,8 +61,16 @@ public:
|
|||||||
//! ~russian Возвращает все заголовки сообщения
|
//! ~russian Возвращает все заголовки сообщения
|
||||||
const PIMap<PIString, PIString> & headers() const { return m_headers; }
|
const PIMap<PIString, PIString> & headers() const { return m_headers; }
|
||||||
|
|
||||||
//! ~english Gets all message arguments
|
//! ~english Gets URL query arguments
|
||||||
//! ~russian Возвращает все аргументы сообщения
|
//! ~russian Возвращает URL query аргументы
|
||||||
|
const PIMap<PIString, PIString> & queryArguments() const { return m_query_arguments; }
|
||||||
|
|
||||||
|
//! ~english Gets URL path arguments
|
||||||
|
//! ~russian Возвращает URL path аргументы
|
||||||
|
const PIMap<PIString, PIString> & pathArguments() const { return m_path_arguments; }
|
||||||
|
|
||||||
|
//! ~english Gets all message arguments (query + path)
|
||||||
|
//! ~russian Возвращает все аргументы сообщения (query + path)
|
||||||
const PIMap<PIString, PIString> & arguments() const { return m_arguments; }
|
const PIMap<PIString, PIString> & arguments() const { return m_arguments; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -71,7 +79,7 @@ protected:
|
|||||||
PIString m_path;
|
PIString m_path;
|
||||||
PIByteArray m_body;
|
PIByteArray m_body;
|
||||||
PIMap<PIString, PIString> m_headers;
|
PIMap<PIString, PIString> m_headers;
|
||||||
PIMap<PIString, PIString> m_arguments;
|
PIMap<PIString, PIString> m_query_arguments, m_path_arguments, m_arguments;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -96,7 +104,11 @@ public:
|
|||||||
MessageMutable & setBody(PIByteArray b);
|
MessageMutable & setBody(PIByteArray b);
|
||||||
|
|
||||||
const PIMap<PIString, PIString> & headers() const { return m_headers; }
|
const PIMap<PIString, PIString> & headers() const { return m_headers; }
|
||||||
|
PIMap<PIString, PIString> & arguments() { return m_arguments; }
|
||||||
const PIMap<PIString, PIString> & arguments() const { return m_arguments; }
|
const PIMap<PIString, PIString> & arguments() const { return m_arguments; }
|
||||||
|
const PIMap<PIString, PIString> & queryArguments() const { return m_query_arguments; }
|
||||||
|
const PIMap<PIString, PIString> & pathArguments() const { return m_path_arguments; }
|
||||||
|
|
||||||
PIMap<PIString, PIString> & headers() { return m_headers; }
|
PIMap<PIString, PIString> & headers() { return m_headers; }
|
||||||
|
|
||||||
//! ~english Adds a header to the message
|
//! ~english Adds a header to the message
|
||||||
@@ -107,15 +119,29 @@ public:
|
|||||||
//! ~russian Удаляет заголовок из сообщения
|
//! ~russian Удаляет заголовок из сообщения
|
||||||
MessageMutable & removeHeader(const PIString & header);
|
MessageMutable & removeHeader(const PIString & header);
|
||||||
|
|
||||||
PIMap<PIString, PIString> & arguments() { return m_arguments; }
|
//! ~english Gets reference to URL query arguments
|
||||||
|
//! ~russian Возвращает ссылку на URL query аргументы
|
||||||
|
PIMap<PIString, PIString> & queryArguments() { return m_query_arguments; }
|
||||||
|
|
||||||
//! ~english Adds an argument to the message
|
//! ~english Adds an URL query argument to the message
|
||||||
//! ~russian Добавляет аргумент к сообщению
|
//! ~russian Добавляет URL query аргумент к сообщению
|
||||||
MessageMutable & addArgument(const PIString & arg, const PIString & value);
|
MessageMutable & addQueryArgument(const PIString & arg, const PIString & value);
|
||||||
|
|
||||||
//! ~english Removes an argument from the message
|
//! ~english Removes an URL query argument from the message
|
||||||
//! ~russian Удаляет аргумент из сообщения
|
//! ~russian Удаляет URL query аргумент из сообщения
|
||||||
MessageMutable & removeArgument(const PIString & arg);
|
MessageMutable & removeQueryArgument(const PIString & arg);
|
||||||
|
|
||||||
|
//! ~english Gets reference to URL path arguments
|
||||||
|
//! ~russian Возвращает ссылку на URL path аргументы
|
||||||
|
PIMap<PIString, PIString> & pathArguments() { return m_path_arguments; }
|
||||||
|
|
||||||
|
//! ~english Adds an URL path argument to the message
|
||||||
|
//! ~russian Добавляет URL path аргумент к сообщению
|
||||||
|
MessageMutable & addPathArgument(const PIString & arg, const PIString & value);
|
||||||
|
|
||||||
|
//! ~english Removes an URL path argument from the message
|
||||||
|
//! ~russian Удаляет URL query path из сообщения
|
||||||
|
MessageMutable & removePathArgument(const PIString & arg);
|
||||||
|
|
||||||
//! ~english Creates message from HTTP status code
|
//! ~english Creates message from HTTP status code
|
||||||
//! ~russian Создает сообщение из HTTP-статус кода
|
//! ~russian Создает сообщение из HTTP-статус кода
|
||||||
|
|||||||
@@ -17,23 +17,23 @@ public:
|
|||||||
|
|
||||||
//! ~english Registers handler for specific path and HTTP method
|
//! ~english Registers handler for specific path and HTTP method
|
||||||
//! ~russian Регистрирует обработчик для указанного пути и HTTP метода
|
//! ~russian Регистрирует обработчик для указанного пути и HTTP метода
|
||||||
void registerPath(const PIString & path, PIHTTP::Method method, RequestFunction functor);
|
bool registerPath(const PIString & path, PIHTTP::Method method, RequestFunction functor);
|
||||||
|
|
||||||
//! ~english Registers handler for specific path and HTTP method
|
//! ~english Registers handler for specific path and HTTP method
|
||||||
//! ~russian Регистрирует обработчик для указанного пути и HTTP метода
|
//! ~russian Регистрирует обработчик для указанного пути и HTTP метода
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void
|
bool
|
||||||
registerPath(const PIString & path, PIHTTP::Method method, T * o, PIHTTP::MessageMutable (T::*function)(const PIHTTP::MessageConst &)) {
|
registerPath(const PIString & path, PIHTTP::Method method, T * o, PIHTTP::MessageMutable (T::*function)(const PIHTTP::MessageConst &)) {
|
||||||
registerPath(path, method, [o, function](const PIHTTP::MessageConst & m) { return (o->*function)(m); });
|
return registerPath(path, method, [o, function](const PIHTTP::MessageConst & m) { return (o->*function)(m); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//! ~english Registers handler for unhandled requests
|
//! ~english Registers handler for unregistered pathes
|
||||||
//! ~russian Регистрирует обработчик для необработанных запросов
|
//! ~russian Регистрирует обработчик для незарегистрированных путей
|
||||||
void registerUnhandled(RequestFunction functor);
|
void registerUnhandled(RequestFunction functor);
|
||||||
|
|
||||||
//! ~english Registers handler for unhandled requests
|
//! ~english Registers handler for unregistered pathes
|
||||||
//! ~russian Регистрирует обработчик для необработанных запросов
|
//! ~russian Регистрирует обработчик для незарегистрированных путей
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void registerUnhandled(T * o, PIHTTP::MessageMutable (T::*function)(const PIHTTP::MessageConst &)) {
|
void registerUnhandled(T * o, PIHTTP::MessageMutable (T::*function)(const PIHTTP::MessageConst &)) {
|
||||||
registerUnhandled([o, function](const PIHTTP::MessageConst & m) { return (o->*function)(m); });
|
registerUnhandled([o, function](const PIHTTP::MessageConst & m) { return (o->*function)(m); });
|
||||||
@@ -61,14 +61,43 @@ public:
|
|||||||
void clearReplyHeaders() { reply_headers.clear(); }
|
void clearReplyHeaders() { reply_headers.clear(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct PathElement {
|
||||||
|
enum class Type {
|
||||||
|
Invalid = 0x01,
|
||||||
|
Fixed = 0x02,
|
||||||
|
Arguments = 0x04,
|
||||||
|
AnyOne = 0x08,
|
||||||
|
AnyPart = 0x10,
|
||||||
|
AnyMany = 0x20
|
||||||
|
};
|
||||||
|
|
||||||
|
Type type = Type::Fixed;
|
||||||
|
PIString source;
|
||||||
|
PIStringList parts;
|
||||||
|
PIMap<int, PIString> arguments;
|
||||||
|
|
||||||
|
PathElement(const PIString & reg = {});
|
||||||
|
|
||||||
|
bool match(const PIString & in, PIMap<PIString, PIString> & ext_args) const;
|
||||||
|
uint priority() const;
|
||||||
|
};
|
||||||
|
|
||||||
struct Endpoint {
|
struct Endpoint {
|
||||||
bool match(const PIStringList & in_path) const;
|
|
||||||
PIStringList path;
|
PIStringList path;
|
||||||
PIHTTP::Method method = PIHTTP::Method::Unknown;
|
PIHTTP::Method method = PIHTTP::Method::Unknown;
|
||||||
RequestFunction function;
|
RequestFunction function;
|
||||||
|
PIFlags<PathElement::Type> path_types;
|
||||||
|
PIVector<PathElement> prepared_path;
|
||||||
|
uint priority = 0;
|
||||||
|
|
||||||
|
bool create(const PIString & p);
|
||||||
|
bool match(const PIStringList & in_path, PIMap<PIString, PIString> & ext_args) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static PIStringList splitPath(const PIString & path);
|
||||||
|
|
||||||
PIMap<PIString, PIString> reply_headers;
|
PIMap<PIString, PIString> reply_headers;
|
||||||
PIMap<PIString, Endpoint> functions;
|
PIMap<uint, PIVector<Endpoint>> endpoints;
|
||||||
RequestFunction unhandled;
|
RequestFunction unhandled;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public:
|
|||||||
|
|
||||||
//! \~english Constructor with flags = Enum "e"
|
//! \~english Constructor with flags = Enum "e"
|
||||||
//! \~russian Создает флаги со значением = Enum "e"
|
//! \~russian Создает флаги со значением = Enum "e"
|
||||||
PIFlags(Enum e): flags(e) { ; }
|
PIFlags(Enum e): flags((int)e) { ; }
|
||||||
|
|
||||||
//! \~english Constructor with flags = int "i"
|
//! \~english Constructor with flags = int "i"
|
||||||
//! \~russian Создает флаги со значением = int "i"
|
//! \~russian Создает флаги со значением = int "i"
|
||||||
@@ -80,9 +80,9 @@ public:
|
|||||||
//! \~russian Устанавливает флаг "e" в "on"
|
//! \~russian Устанавливает флаг "e" в "on"
|
||||||
PIFlags & setFlag(const Enum & e, bool on = true) {
|
PIFlags & setFlag(const Enum & e, bool on = true) {
|
||||||
if (on)
|
if (on)
|
||||||
flags |= e;
|
flags |= (int)e;
|
||||||
else
|
else
|
||||||
flags &= ~e;
|
flags &= ~(int)e;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ public:
|
|||||||
|
|
||||||
//! \~english Assign operator
|
//! \~english Assign operator
|
||||||
//! \~russian Оператор присваивания
|
//! \~russian Оператор присваивания
|
||||||
void operator=(const Enum & e) { flags = e; }
|
void operator=(const Enum & e) { flags = (int)e; }
|
||||||
|
|
||||||
//! \~english Assign operator
|
//! \~english Assign operator
|
||||||
//! \~russian Оператор присваивания
|
//! \~russian Оператор присваивания
|
||||||
@@ -110,7 +110,7 @@ public:
|
|||||||
|
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
bool operator==(const Enum & e) { return flags == e; }
|
bool operator==(const Enum & e) { return flags == (int)e; }
|
||||||
|
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
@@ -122,7 +122,7 @@ public:
|
|||||||
|
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
bool operator!=(const Enum & e) { return flags != e; }
|
bool operator!=(const Enum & e) { return flags != (int)e; }
|
||||||
|
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
@@ -134,7 +134,7 @@ public:
|
|||||||
|
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
bool operator>(const Enum & e) { return flags > e; }
|
bool operator>(const Enum & e) { return flags > (int)e; }
|
||||||
|
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
@@ -146,7 +146,7 @@ public:
|
|||||||
|
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
bool operator<(const Enum & e) { return flags < e; }
|
bool operator<(const Enum & e) { return flags < (int)e; }
|
||||||
|
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
@@ -158,7 +158,7 @@ public:
|
|||||||
|
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
bool operator>=(const Enum & e) { return flags >= e; }
|
bool operator>=(const Enum & e) { return flags >= (int)e; }
|
||||||
|
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
@@ -170,7 +170,7 @@ public:
|
|||||||
|
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
bool operator<=(const Enum & e) { return flags <= e; }
|
bool operator<=(const Enum & e) { return flags <= (int)e; }
|
||||||
|
|
||||||
//! \~english Compare operator
|
//! \~english Compare operator
|
||||||
//! \~russian Оператор сравнения
|
//! \~russian Оператор сравнения
|
||||||
@@ -182,7 +182,7 @@ public:
|
|||||||
|
|
||||||
//! \~english Bit-wise AND operator
|
//! \~english Bit-wise AND operator
|
||||||
//! \~russian Оператор побитового И
|
//! \~russian Оператор побитового И
|
||||||
void operator&=(const Enum & e) { flags &= e; }
|
void operator&=(const Enum & e) { flags &= (int)e; }
|
||||||
|
|
||||||
//! \~english Bit-wise AND operator
|
//! \~english Bit-wise AND operator
|
||||||
//! \~russian Оператор побитового И
|
//! \~russian Оператор побитового И
|
||||||
@@ -194,7 +194,7 @@ public:
|
|||||||
|
|
||||||
//! \~english Bit-wise OR operator
|
//! \~english Bit-wise OR operator
|
||||||
//! \~russian Оператор побитового ИЛИ
|
//! \~russian Оператор побитового ИЛИ
|
||||||
void operator|=(const Enum & e) { flags |= e; }
|
void operator|=(const Enum & e) { flags |= (int)e; }
|
||||||
|
|
||||||
//! \~english Bit-wise OR operator
|
//! \~english Bit-wise OR operator
|
||||||
//! \~russian Оператор побитового ИЛИ
|
//! \~russian Оператор побитового ИЛИ
|
||||||
@@ -206,7 +206,7 @@ public:
|
|||||||
|
|
||||||
//! \~english Bit-wise XOR operator
|
//! \~english Bit-wise XOR operator
|
||||||
//! \~russian Оператор побитового исключающего ИЛИ
|
//! \~russian Оператор побитового исключающего ИЛИ
|
||||||
void operator^=(const Enum & e) { flags ^= e; }
|
void operator^=(const Enum & e) { flags ^= (int)e; }
|
||||||
|
|
||||||
//! \~english Bit-wise XOR operator
|
//! \~english Bit-wise XOR operator
|
||||||
//! \~russian Оператор побитового исключающего ИЛИ
|
//! \~russian Оператор побитового исключающего ИЛИ
|
||||||
@@ -222,7 +222,7 @@ public:
|
|||||||
//! \~english Bit-wise AND operator
|
//! \~english Bit-wise AND operator
|
||||||
//! \~russian Оператор побитового И
|
//! \~russian Оператор побитового И
|
||||||
PIFlags operator&(Enum e) const {
|
PIFlags operator&(Enum e) const {
|
||||||
PIFlags tf(flags & e);
|
PIFlags tf(flags & (int)e);
|
||||||
return tf;
|
return tf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,7 +243,7 @@ public:
|
|||||||
//! \~english Bit-wise OR operator
|
//! \~english Bit-wise OR operator
|
||||||
//! \~russian Оператор побитового ИЛИ
|
//! \~russian Оператор побитового ИЛИ
|
||||||
PIFlags operator|(Enum e) const {
|
PIFlags operator|(Enum e) const {
|
||||||
PIFlags tf(flags | e);
|
PIFlags tf(flags | (int)e);
|
||||||
return tf;
|
return tf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,7 +264,7 @@ public:
|
|||||||
//! \~english Bit-wise XOR operator
|
//! \~english Bit-wise XOR operator
|
||||||
//! \~russian Оператор побитового исключающего ИЛИ
|
//! \~russian Оператор побитового исключающего ИЛИ
|
||||||
PIFlags operator^(Enum e) const {
|
PIFlags operator^(Enum e) const {
|
||||||
PIFlags tf(flags ^ e);
|
PIFlags tf(flags ^ (int)e);
|
||||||
return tf;
|
return tf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,7 +277,7 @@ public:
|
|||||||
|
|
||||||
//! \~english Test flag operator
|
//! \~english Test flag operator
|
||||||
//! \~russian Оператор проверки флага
|
//! \~russian Оператор проверки флага
|
||||||
bool operator[](Enum e) const { return (flags & e) == e; }
|
bool operator[](Enum e) const { return (flags & (int)e) == (int)e; }
|
||||||
|
|
||||||
//! \~english Implicity conversion to \c int
|
//! \~english Implicity conversion to \c int
|
||||||
//! \~russian Оператор неявного преобразования в \c int
|
//! \~russian Оператор неявного преобразования в \c int
|
||||||
|
|||||||
83
main.cpp
83
main.cpp
@@ -80,12 +80,69 @@ void piDeserializeJSON(S & v, const PIJSON & js) {
|
|||||||
piDeserializeJSON(v.re, js["re"]);
|
piDeserializeJSON(v.re, js["re"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PIKbdListener kbd;
|
||||||
|
|
||||||
int main(int argc, char * argv[]) {
|
int main(int argc, char * argv[]) {
|
||||||
|
PIHTTPServer server;
|
||||||
|
server.listen({"127.0.0.1:7777"});
|
||||||
|
// server.setBasicAuthRealm("pip");
|
||||||
|
// server.setBasicAuthEnabled(true);
|
||||||
|
// server.setBasicAuthCallback([](const PIString & u, const PIString & p) -> bool {
|
||||||
|
// piCout << "basic auth" << u << p;
|
||||||
|
// return (u == "u" && p == "p");
|
||||||
|
auto reg = [&server](const PIString & path) {
|
||||||
|
server.registerPath(path, Method::Get, [path](const PIHTTP::MessageConst & msg) -> PIHTTP::MessageMutable {
|
||||||
|
piCout << "\nserver rec:\n\tpath: %1\n\t url: %2\n\t args: %3\n\tQ args: %4\n\tP args: %5"_a.arg(path)
|
||||||
|
.arg(msg.path())
|
||||||
|
.arg(piStringify(msg.arguments()))
|
||||||
|
.arg(piStringify(msg.queryArguments()))
|
||||||
|
.arg(piStringify(msg.pathArguments()));
|
||||||
|
return MessageMutable().setCode(Code::Accepted);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// });
|
||||||
|
|
||||||
|
reg("/*/3/get");
|
||||||
|
reg("/*/{ID}/get");
|
||||||
|
reg("/api/{ID}/get");
|
||||||
|
reg("/api/1/get");
|
||||||
|
server.unregisterPath("*/{ID}/get");
|
||||||
|
// reg("/api/1/bort{bortID}/get");
|
||||||
|
// reg("/api/**");
|
||||||
|
// reg("/api/1/bort2/get");
|
||||||
|
// reg("/api/**/bort2/get");
|
||||||
|
|
||||||
|
/*server.registerPath("api/{ID}/bort{bortID}/get", Method::Get, [](const PIHTTP::MessageConst & msg) -> PIHTTP::MessageMutable {
|
||||||
|
piCout << "server rec:\n\tpath: %1\n\targs: %2\n\tQ args: %3\n\tP args: %4\n"_a.arg(msg.path())
|
||||||
|
.arg(piStringify(msg.arguments()))
|
||||||
|
.arg(piStringify(msg.queryArguments()))
|
||||||
|
.arg(piStringify(msg.pathArguments()));
|
||||||
|
return MessageMutable().setCode(Code::Accepted);
|
||||||
|
});
|
||||||
|
server.registerPath("sendMessage", Method::Post, [](const PIHTTP::MessageConst & msg) -> PIHTTP::MessageMutable {
|
||||||
|
return MessageMutable().setCode(Code::Accepted);
|
||||||
|
});
|
||||||
|
server.registerUnhandled([](const PIHTTP::MessageConst & msg) -> PIHTTP::MessageMutable {
|
||||||
|
PIHTTP::MessageMutable ret;
|
||||||
|
piCout << "server rec:\n\tpath: %1\n\tmethod: %2\n\targs: %3\n\theaders: %4\n\tbody: %5\n"_a.arg(msg.path())
|
||||||
|
.arg(PIHTTP::methodName(msg.method()))
|
||||||
|
.arg(piStringify(msg.arguments()))
|
||||||
|
.arg(PIStringList(msg.headers().map<PIString>([](PIString k, PIString v) { return k + " = " + v; })).join("\n\t\t "))
|
||||||
|
.arg(PIString::fromUTF8(msg.body()));
|
||||||
|
ret.setCode(PIHTTP::Code::BadRequest);
|
||||||
|
ret.setBody(PIByteArray::fromAscii("hello client! 0123456789"));
|
||||||
|
return ret;
|
||||||
|
});*/
|
||||||
|
kbd.enableExitCapture('Q');
|
||||||
|
WAIT_FOR_EXIT;
|
||||||
|
return 0;
|
||||||
|
|
||||||
// PIRegularExpression pire("привет"_u8, PIRegularExpression::CaseInsensitive);
|
// PIRegularExpression pire("привет"_u8, PIRegularExpression::CaseInsensitive);
|
||||||
// PIString subj = "the dog ПриВет sat on the cat"_u8;
|
// PIString subj = "the dog ПриВет sat on the cat"_u8;
|
||||||
// PIRegularExpression pire("^(?<date>\\d\\d)/(?<month>\\d\\d)/(?<year>\\d\\d\\d\\d)$"_u8);
|
// PIRegularExpression pire("^(?<date>\\d\\d)/(?<month>\\d\\d)/(?<year>\\d\\d\\d\\d)$"_u8);
|
||||||
// PIString subj = "08/12/1985"_u8;
|
// PIString subj = "08/12/1985"_u8;
|
||||||
|
|
||||||
|
|
||||||
PIString pat = "*.Exe";
|
PIString pat = "*.Exe";
|
||||||
PIRegularExpression re_g = PIRegularExpression::fromGlob(pat, PIRegularExpression::CaseInsensitive);
|
PIRegularExpression re_g = PIRegularExpression::fromGlob(pat, PIRegularExpression::CaseInsensitive);
|
||||||
PIRegularExpression re_p = PIRegularExpression::fromPOSIX(pat, PIRegularExpression::CaseInsensitive);
|
PIRegularExpression re_p = PIRegularExpression::fromPOSIX(pat, PIRegularExpression::CaseInsensitive);
|
||||||
@@ -231,32 +288,6 @@ int main(int argc, char * argv[]) {
|
|||||||
// piCout << "512:" << sha5xx(src, initial_512, 64).toHex();
|
// piCout << "512:" << sha5xx(src, initial_512, 64).toHex();
|
||||||
return 0;*/
|
return 0;*/
|
||||||
|
|
||||||
/*PIHTTPServer server;
|
|
||||||
server.listen({"127.0.0.1:7777"});
|
|
||||||
// server.setBasicAuthRealm("pip");
|
|
||||||
// server.setBasicAuthEnabled(true);
|
|
||||||
// server.setBasicAuthCallback([](const PIString & u, const PIString & p) -> bool {
|
|
||||||
// piCout << "basic auth" << u << p;
|
|
||||||
// return (u == "u" && p == "p");
|
|
||||||
// });
|
|
||||||
server.registerPath("sendMessage", Method::Post, [](const PIHTTP::MessageConst & msg) -> PIHTTP::MessageMutable {
|
|
||||||
return MessageMutable().setCode(Code::Accepted);
|
|
||||||
});
|
|
||||||
server.registerUnhandled([](const PIHTTP::MessageConst & msg) -> PIHTTP::MessageMutable {
|
|
||||||
PIHTTP::MessageMutable ret;
|
|
||||||
piCout << "server rec:\n\tpath: %1\n\tmethod: %2\n\targs: %3\n\theaders: %4\n\tbody: %5\n"_a.arg(msg.path())
|
|
||||||
.arg(PIHTTP::methodName(msg.method()))
|
|
||||||
.arg(piStringify(msg.arguments()))
|
|
||||||
.arg(PIStringList(msg.headers().map<PIString>([](PIString k, PIString v) { return k + " = " + v; })).join("\n\t\t "))
|
|
||||||
.arg(PIString::fromUTF8(msg.body()));
|
|
||||||
ret.setCode(PIHTTP::Code::BadRequest);
|
|
||||||
ret.setBody(PIByteArray::fromAscii("hello client! 0123456789"));
|
|
||||||
piSleep(5.);
|
|
||||||
return ret;
|
|
||||||
});
|
|
||||||
kbd.waitForFinish();
|
|
||||||
return 0;*/
|
|
||||||
|
|
||||||
/*PIHTTP::MessageMutable req;
|
/*PIHTTP::MessageMutable req;
|
||||||
req.setBody(PIByteArray::fromAscii("hello server!")).addArgument("a0", "val.0").addArgument("a~r1", "знач,1"_u8);
|
req.setBody(PIByteArray::fromAscii("hello server!")).addArgument("a0", "val.0").addArgument("a~r1", "знач,1"_u8);
|
||||||
auto * c = PIHTTPClient::create("http://u:p@127.0.0.1:7777/api", PIHTTP::Method::Get, req);
|
auto * c = PIHTTPClient::create("http://u:p@127.0.0.1:7777/api", PIHTTP::Method::Get, req);
|
||||||
|
|||||||
Reference in New Issue
Block a user