#include "ParkingStatusHttpServer.h" #include #include #include #include #include #include "Poco/Exception.h" #include "Poco/Net/HTTPServer.h" #include "Poco/Net/HTTPRequest.h" #include "Poco/Net/HTTPRequestHandler.h" #include "Poco/Net/HTTPRequestHandlerFactory.h" #include "Poco/Net/HTTPServerParams.h" #include "Poco/Net/HTTPServerRequest.h" #include "Poco/Net/HTTPServerResponse.h" #include "Poco/Net/ServerSocket.h" #include "Poco/Net/SocketAddress.h" #include "Poco/URI.h" namespace { const char* kStatusPath = "/api/parking/status"; bool IsStatusPath(const std::string& path) { return path == "/" || path == "/status" || path == "/api/status" || path == kStatusPath; } void WriteJson(Poco::Net::HTTPServerResponse& response, Poco::Net::HTTPResponse::HTTPStatus status, const std::string& body) { response.setStatus(status); response.setContentType("application/json; charset=utf-8"); response.set("Cache-Control", "no-store"); response.setContentLength(static_cast(body.size())); std::ostream& output = response.send(); output.write(body.data(), static_cast(body.size())); } class StatusRequestHandler : public Poco::Net::HTTPRequestHandler { public: explicit StatusRequestHandler(ParkingStatusHttpServer::StatusProvider statusProvider) : m_statusProvider(std::move(statusProvider)) { } void handleRequest(Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response) override { if (request.getMethod() != Poco::Net::HTTPRequest::HTTP_GET) { WriteJson(response, Poco::Net::HTTPResponse::HTTP_METHOD_NOT_ALLOWED, "{\"success\":false,\"message\":\"请求方法不支持\"}"); return; } const std::string path = Poco::URI(request.getURI()).getPath(); if (!IsStatusPath(path)) { WriteJson(response, Poco::Net::HTTPResponse::HTTP_NOT_FOUND, "{\"success\":false,\"message\":\"接口不存在\"}"); return; } const std::string body = m_statusProvider ? m_statusProvider() : std::string("{\"success\":false,\"message\":\"状态服务不可用\"}"); WriteJson(response, Poco::Net::HTTPResponse::HTTP_OK, body); } private: ParkingStatusHttpServer::StatusProvider m_statusProvider; }; class StatusRequestHandlerFactory : public Poco::Net::HTTPRequestHandlerFactory { public: explicit StatusRequestHandlerFactory(ParkingStatusHttpServer::StatusProvider statusProvider) : m_statusProvider(std::move(statusProvider)) { } Poco::Net::HTTPRequestHandler* createRequestHandler(const Poco::Net::HTTPServerRequest&) override { return new StatusRequestHandler(m_statusProvider); } private: ParkingStatusHttpServer::StatusProvider m_statusProvider; }; } // namespace ParkingStatusHttpServer::ParkingStatusHttpServer() = default; ParkingStatusHttpServer::~ParkingStatusHttpServer() { Stop(); } int ParkingStatusHttpServer::Start(const HttpServerConfig& config, StatusProvider statusProvider) { Stop(); m_lastError.clear(); if (!config.enabled) { return 0; } if (!statusProvider) { m_lastError = "HTTP状态服务缺少状态提供函数"; return -1; } try { if (config.port <= 0 || config.port > 65535) { m_lastError = "HTTP状态服务端口无效"; return -1; } const int maxQueued = std::max(1, config.maxQueued); const std::string listenAddress = config.address.empty() ? "0.0.0.0" : config.address; Poco::Net::ServerSocket socket; socket.bind(Poco::Net::SocketAddress(listenAddress, config.port), true); socket.listen(maxQueued); Poco::Net::HTTPServerParams* params = new Poco::Net::HTTPServerParams(); params->setMaxQueued(maxQueued); params->setMaxThreads(std::max(1, config.maxThreads)); m_server.reset(new Poco::Net::HTTPServer( new StatusRequestHandlerFactory(std::move(statusProvider)), socket, params)); m_server->start(); m_running = true; return 0; } catch (const Poco::Exception& e) { m_lastError = e.displayText(); } catch (const std::exception& e) { m_lastError = e.what(); } catch (...) { m_lastError = "HTTP状态服务启动异常"; } m_server.reset(); m_running = false; return -1; } void ParkingStatusHttpServer::Stop() { if (m_server) { m_server->stopAll(true); m_server.reset(); } m_running = false; } bool ParkingStatusHttpServer::IsRunning() const { return m_running; } std::string ParkingStatusHttpServer::LastError() const { return m_lastError; }