You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
120 lines
3.6 KiB
120 lines
3.6 KiB
#include <http.hpp> |
|
#include <json_converters.hpp> |
|
#include <orders.hpp> |
|
#include <store.hpp> |
|
|
|
void Application::web_server_started(std::size_t port) { |
|
std::cout << "Web server started and listening on " << port << ".\n"; |
|
}; |
|
|
|
void Application::secure_web_server_started(std::size_t port) { |
|
std::cout << "Secure web server started and listening on " << port << ".\n"; |
|
}; |
|
|
|
Application::Application(const nlohmann::json &cfg) { |
|
convert::from_json(cfg.value("http", json::object()), http_server.config); |
|
if (cfg.contains("https")) { |
|
const auto https = cfg["https"]; |
|
if (https.contains("cert") && https.contains("key")) { |
|
https_server = std::make_shared<HttpsServer>(https["cert"], https["key"]); |
|
} |
|
} |
|
|
|
if (https_server) { |
|
convert::from_json(cfg.value("https", json::object()), |
|
https_server->config); |
|
} |
|
} |
|
|
|
int Application::run() { |
|
std::vector<std::thread> servers; |
|
orders orders(data_directory); |
|
|
|
for (const auto &m : {"GET", "POST", "PUT", "PATCH", "OPTIONS", "HEAD"}) { |
|
if (https_server) { |
|
https_server->default_resource[m] = |
|
[](std::shared_ptr<HttpsServer::Response> response, ...) { |
|
return response::not_found(response); |
|
}; |
|
} |
|
http_server.default_resource[m] = |
|
[](std::shared_ptr<HttpServer::Response> response, ...) { |
|
return response::not_found(response); |
|
}; |
|
} |
|
|
|
if (https_server) { |
|
servers.emplace_back( |
|
[&]() { https_server->start(secure_web_server_started); }); |
|
} |
|
|
|
http_server.resource["^/orders/?$"]["GET"] = |
|
[&](std::shared_ptr<HttpServer::Response> response, ...) { |
|
response->write(Status::success_ok, json({}).dump(), |
|
{header_access_control, header_application_data}); |
|
}; |
|
http_server.resource["^/stop/?$"]["PUT"] = |
|
[&](std::shared_ptr<HttpServer::Response> response, ...) { |
|
{ response->write("stopping"); } |
|
http_server.stop(); |
|
if (https_server) |
|
https_server->stop(); |
|
}; |
|
|
|
http_server.resource["^/orders/?$"]["PUT"] = |
|
[&](std::shared_ptr<HttpServer::Response> response, |
|
std::shared_ptr<HttpServer::Request> request) { |
|
const auto content_type = request->header.find("Content-Type"); |
|
|
|
const auto missing_content_type = content_type == request->header.end(); |
|
if (missing_content_type) { |
|
return response::not_found(response); |
|
} |
|
|
|
const auto is_json = content_type->second == "application/json"; |
|
if (!is_json) { |
|
return response::not_found(response); |
|
} |
|
|
|
json data = nullptr; |
|
try { |
|
request->content >> data; |
|
} catch (...) { |
|
return response::not_found(response); |
|
} |
|
|
|
if (!data.is_object()) { |
|
return response::not_found(response); |
|
} |
|
|
|
data_validator v; |
|
|
|
if (v.validate(data)) { |
|
return response::bad_request(response, v.errors()); |
|
} |
|
|
|
orders.push(data); |
|
orders.write(); |
|
|
|
response->write(Status::success_created, data.dump(), |
|
{header_access_control, header_application_data}); |
|
}; |
|
|
|
http_server.on_error = [](std::shared_ptr<HttpServer::Request> request, |
|
const SimpleWeb::error_code &ec) { |
|
std::cout << ec.message() << ", " << ec.category().name() << std::endl; |
|
}; |
|
|
|
servers.emplace_back([&]() { http_server.start(web_server_started); }); |
|
|
|
for (auto &server : servers) { |
|
server.join(); |
|
} |
|
|
|
return 0; |
|
} |
|
|
|
Application &Application::get(const json &config) { |
|
static Application app(config); |
|
return app; |
|
}
|
|
|