88 lines
2.5 KiB
C++
88 lines
2.5 KiB
C++
#include "pihttpserver.h"
|
|
|
|
#include "piserverendpoint_p.h"
|
|
|
|
|
|
struct Endpoint: public PIHTTP::ServerEndpoint {
|
|
PIHTTP::Method method = PIHTTP::Method::Unknown;
|
|
PIHTTPServer::RequestFunction function;
|
|
};
|
|
|
|
|
|
PRIVATE_DEFINITION_START(PIHTTPServer)
|
|
PIMap<uint, PIVector<Endpoint>> endpoints;
|
|
PRIVATE_DEFINITION_END(PIHTTPServer)
|
|
|
|
|
|
PIHTTPServer::PIHTTPServer() {
|
|
setRequestCallback([this](const PIHTTP::MessageConst & r) -> PIHTTP::MessageMutable {
|
|
PIHTTP::MessageMutable reply;
|
|
reply.setCode(PIHTTP::Code::NotFound);
|
|
auto in_path = PIHTTP::ServerEndpoint::splitPath(r.path());
|
|
auto it = PRIVATE->endpoints.makeReverseIterator();
|
|
bool found = false;
|
|
while (it.next()) {
|
|
for (const auto & ep: it.value()) {
|
|
if (ep.function && ep.method == r.method()) {
|
|
PIMap<PIString, PIString> ext_args;
|
|
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;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (found) break;
|
|
}
|
|
if (!found && unhandled) reply = unhandled(r);
|
|
auto hit = reply_headers.makeIterator();
|
|
while (hit.next())
|
|
reply.addHeader(hit.key(), hit.value());
|
|
return reply;
|
|
});
|
|
}
|
|
|
|
|
|
PIHTTPServer::~PIHTTPServer() {
|
|
stop();
|
|
}
|
|
|
|
|
|
bool PIHTTPServer::registerPath(const PIString & path, PIHTTP::Method method, RequestFunction functor) {
|
|
Endpoint ep;
|
|
if (!ep.create(path)) return false;
|
|
ep.method = method;
|
|
ep.function = std::move(functor);
|
|
PRIVATE->endpoints[ep.priority] << ep;
|
|
return true;
|
|
}
|
|
|
|
|
|
void PIHTTPServer::registerUnhandled(RequestFunction functor) {
|
|
unhandled = functor;
|
|
}
|
|
|
|
|
|
void PIHTTPServer::unregisterPath(const PIString & path, PIHTTP::Method method) {
|
|
auto pl = PIHTTP::ServerEndpoint::splitPath(path);
|
|
auto it = PRIVATE->endpoints.makeIterator();
|
|
while (it.next()) {
|
|
it.value().removeWhere([&pl, method](const Endpoint & ep) { return ep.path == pl && ep.method == method; });
|
|
}
|
|
PRIVATE->endpoints.removeWhere([](uint, const PIVector<Endpoint> & epl) { return epl.isEmpty(); });
|
|
}
|
|
|
|
|
|
void PIHTTPServer::unregisterPath(const PIString & path) {
|
|
auto pl = PIHTTP::ServerEndpoint::splitPath(path);
|
|
auto it = PRIVATE->endpoints.makeIterator();
|
|
while (it.next()) {
|
|
it.value().removeWhere([&pl](const Endpoint & ep) { return ep.path == pl; });
|
|
}
|
|
PRIVATE->endpoints.removeWhere([](uint, const PIVector<Endpoint> & epl) { return epl.isEmpty(); });
|
|
}
|