| 147 | } |
| 148 | |
| 149 | void HttpServer::Start() |
| 150 | { |
| 151 | std::lock_guard<std::mutex> lock(_impl->mutex); |
| 152 | |
| 153 | if (_impl->server) { |
| 154 | _impl->server->stop(); |
| 155 | } |
| 156 | if (_impl->thread.joinable()) { |
| 157 | _impl->thread.join(); |
| 158 | } |
| 159 | |
| 160 | _impl->server = std::make_unique<httplib::Server>(); |
| 161 | _impl->listening.store(false); |
| 162 | |
| 163 | auto handleRequest = [this](const httplib::Request &req, |
| 164 | httplib::Response &res) { |
| 165 | HttpRequest request; |
| 166 | request.method = req.method; |
| 167 | request.path = req.path; |
| 168 | request.body = req.body; |
| 169 | for (const auto &[name, value] : req.headers) { |
| 170 | request.headers.emplace(name, value); |
| 171 | } |
| 172 | _impl->dispatcher.DispatchMessage(request); |
| 173 | res.status = 200; |
| 174 | }; |
| 175 | |
| 176 | _impl->server->Get(".*", handleRequest); |
| 177 | _impl->server->Post(".*", handleRequest); |
| 178 | _impl->server->Put(".*", handleRequest); |
| 179 | _impl->server->Patch(".*", handleRequest); |
| 180 | _impl->server->Delete(".*", handleRequest); |
| 181 | |
| 182 | const int port = _port; |
| 183 | const std::string name = _name; |
| 184 | auto serverPtr = _impl->server.get(); |
| 185 | auto listeningFlag = &_impl->listening; |
| 186 | |
| 187 | _impl->thread = std::thread([serverPtr, listeningFlag, port, name]() { |
| 188 | if (!serverPtr->bind_to_port("0.0.0.0", port)) { |
| 189 | blog(LOG_WARNING, |
| 190 | "HTTP server \"%s\" failed to bind to port %d", |
| 191 | name.c_str(), port); |
| 192 | return; |
| 193 | } |
| 194 | listeningFlag->store(true); |
| 195 | blog(LOG_INFO, "HTTP server \"%s\" listening on port %d", |
| 196 | name.c_str(), port); |
| 197 | serverPtr->listen_after_bind(); |
| 198 | listeningFlag->store(false); |
| 199 | blog(LOG_INFO, "HTTP server \"%s\" stopped", name.c_str()); |
| 200 | }); |
| 201 | } |
| 202 | |
| 203 | void HttpServer::Stop() |
| 204 | { |
no test coverage detected