From aebe139d00b44684158edb3616da5c37b12db6d1 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Sun, 26 Apr 2020 13:01:19 +0200 Subject: Added stats output --- response.cpp | 63 ++++++++++++++++++++++++++---------------------------------- 1 file changed, 27 insertions(+), 36 deletions(-) (limited to 'response.cpp') diff --git a/response.cpp b/response.cpp index c5ba426..696b859 100644 --- a/response.cpp +++ b/response.cpp @@ -79,10 +79,11 @@ bool is_ipv6_address(const std::string& addr) std::unordered_map> GetServerParamFunctions{ // following are the supported fields: - {"version", [](Server& server) { return Server::VersionString; }}, {"address", [](Server& server) { return server.GetSocket().address; }}, {"ipv6", [](Server& server) { return is_ipv6_address(server.GetSocket().address) ? "yes" : "no"; }}, {"port", [](Server& server) { return server.GetSocket().port; }}, + {"statistics", [](Server& server) { return server.GetStatistics().getValues(); }}, + {"version", [](Server& server) { return Server::VersionString; }}, }; std::string GetServerParam(const std::string& key, Server& server) @@ -233,42 +234,34 @@ mime_type(beast::string_view path) return "application/text"; } -// Used to return errors by generating response page and HTTP status code response_type HttpStatus(std::string status, std::string message, response_type& res) { - res.result(unsigned(stoul(status))); - res.set(http::field::content_type, "text/html"); - if (res.result_int() == 401) - res.set(http::field::www_authenticate, "Basic realm=\"Webbox Login\""); - res.body() = "

"s + Server::VersionString + " Error

"s + status + " "s + message + "

"s; - res.prepare_payload(); + if (status != "200") { // already handled at res init + res.result(unsigned(stoul(status))); + res.set(http::field::content_type, "text/html"); + if (res.result_int() == 401) + res.set(http::field::www_authenticate, "Basic realm=\"Webbox Login\""); + res.body() = "

"s + Server::VersionString + " Error

"s + status + " "s + message + "

"s; + res.prepare_payload(); + } return res; } -// Do statistics at end of response generation, handle all exit paths via RAII -class StatisticsGuard +// Used to return errors by generating response page and HTTP status code +response_type HttpStatusAndStats(std::string status, std::string message, RequestContext& req_ctx, response_type& res) { - request_type& mReq; - response_type& mRes; - Server& mServer; -public: - StatisticsGuard(request_type& req, response_type& res, Server& server) - : mReq(req) - , mRes(res) - , mServer(server) - { - } + HttpStatus(status, message, res); - ~StatisticsGuard() - { - mServer.GetStatistics().count(mReq.body().size(), - mRes.body().size(), - mRes.result_int() == 200, - is_ipv6_address(mServer.GetSocket().address), - mServer.GetSocket().protocol == SocketProtocol::HTTPS); - } -}; + req_ctx.GetServer().GetStatistics().count( + req_ctx.GetReq().body().size(), + res.body().size(), + res.result_int() != 200, + is_ipv6_address(req_ctx.GetServer().GetSocket().address), + req_ctx.GetServer().GetSocket().protocol == SocketProtocol::HTTPS); + + return std::move(res); +} } // anonymous namespace @@ -279,8 +272,6 @@ response_type generate_response(request_type& req, Server& server) res.set(http::field::content_type, mime_type(extend_index_html(std::string(req.target())))); res.keep_alive(req.keep_alive()); - StatisticsGuard statsGuard{req, res, server}; - try { RequestContext req_ctx{req, server}; // can throw std::out_of_range @@ -288,21 +279,21 @@ response_type generate_response(request_type& req, Server& server) if (auth.size() != 0) { std::string authorization{req[http::field::authorization]}; if (authorization.substr(0, 6) != "Basic "s) - return HttpStatus("401", "Bad Authorization Type", res); + return HttpStatusAndStats("401", "Bad Authorization Type", req_ctx, res); authorization = authorization.substr(6); authorization = decode64(authorization); size_t pos {authorization.find(':')}; if (pos == authorization.npos) - return HttpStatus("401", "Bad Authorization Encoding", res); + return HttpStatusAndStats("401", "Bad Authorization Encoding", req_ctx, res); std::string login{authorization.substr(0, pos)}; std::string password{authorization.substr(pos + 1)}; auto it {auth.find(login)}; if (it == auth.end() || it->second != password) - return HttpStatus("401", "Bad Authorization", res); + return HttpStatusAndStats("401", "Bad Authorization", req_ctx, res); } plugin_type plugin{req_ctx.GetPlugin()}; @@ -318,8 +309,8 @@ response_type generate_response(request_type& req, Server& server) res.body() = res_data; res.prepare_payload(); } - - return res; + + return HttpStatusAndStats("200", "OK", req_ctx, res); } catch(const std::out_of_range& ex) { return HttpStatus("400", "Bad request: Host "s + std::string{req["host"]} + ":"s + std::string{req.target()} + " unknown"s, res); } catch(const std::exception& ex) { -- cgit v1.2.3