#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> 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 ext_args; if (ep.match(in_path, ext_args)) { auto & r_mut(static_cast(const_cast(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, PIHTTP::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(PIHTTP::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 & 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 & epl) { return epl.isEmpty(); }); }