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:
2025-08-28 19:48:19 +03:00
parent 27f37c9cc1
commit ef8b785ac6
8 changed files with 327 additions and 120 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -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-статус кода

View File

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

View File

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

View File

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