summaryrefslogtreecommitdiff
path: root/src/web_service/web_backend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/web_service/web_backend.cpp')
-rw-r--r--src/web_service/web_backend.cpp69
1 files changed, 32 insertions, 37 deletions
diff --git a/src/web_service/web_backend.cpp b/src/web_service/web_backend.cpp
index 09d1651ac..534960d09 100644
--- a/src/web_service/web_backend.cpp
+++ b/src/web_service/web_backend.cpp
@@ -6,13 +6,14 @@
6#include <cstdlib> 6#include <cstdlib>
7#include <mutex> 7#include <mutex>
8#include <string> 8#include <string>
9
9#include <LUrlParser.h> 10#include <LUrlParser.h>
10#include <fmt/format.h> 11#include <fmt/format.h>
11#include <httplib.h> 12#include <httplib.h>
12#include "common/common_types.h" 13
13#include "common/logging/log.h" 14#include "common/logging/log.h"
14#include "common/web_result.h"
15#include "web_service/web_backend.h" 15#include "web_service/web_backend.h"
16#include "web_service/web_result.h"
16 17
17namespace WebService { 18namespace WebService {
18 19
@@ -33,17 +34,16 @@ struct Client::Impl {
33 } 34 }
34 35
35 /// A generic function handles POST, GET and DELETE request together 36 /// A generic function handles POST, GET and DELETE request together
36 Common::WebResult GenericRequest(const std::string& method, const std::string& path, 37 WebResult GenericRequest(const std::string& method, const std::string& path,
37 const std::string& data, bool allow_anonymous, 38 const std::string& data, bool allow_anonymous,
38 const std::string& accept) { 39 const std::string& accept) {
39 if (jwt.empty()) { 40 if (jwt.empty()) {
40 UpdateJWT(); 41 UpdateJWT();
41 } 42 }
42 43
43 if (jwt.empty() && !allow_anonymous) { 44 if (jwt.empty() && !allow_anonymous) {
44 LOG_ERROR(WebService, "Credentials must be provided for authenticated requests"); 45 LOG_ERROR(WebService, "Credentials must be provided for authenticated requests");
45 return Common::WebResult{Common::WebResult::Code::CredentialsMissing, 46 return WebResult{WebResult::Code::CredentialsMissing, "Credentials needed", ""};
46 "Credentials needed", ""};
47 } 47 }
48 48
49 auto result = GenericRequest(method, path, data, accept, jwt); 49 auto result = GenericRequest(method, path, data, accept, jwt);
@@ -62,33 +62,30 @@ struct Client::Impl {
62 * username + token is used if jwt is empty but username and token are 62 * username + token is used if jwt is empty but username and token are
63 * not empty anonymous if all of jwt, username and token are empty 63 * not empty anonymous if all of jwt, username and token are empty
64 */ 64 */
65 Common::WebResult GenericRequest(const std::string& method, const std::string& path, 65 WebResult GenericRequest(const std::string& method, const std::string& path,
66 const std::string& data, const std::string& accept, 66 const std::string& data, const std::string& accept,
67 const std::string& jwt = "", const std::string& username = "", 67 const std::string& jwt = "", const std::string& username = "",
68 const std::string& token = "") { 68 const std::string& token = "") {
69 if (cli == nullptr) { 69 if (cli == nullptr) {
70 auto parsedUrl = LUrlParser::clParseURL::ParseURL(host); 70 const auto parsedUrl = LUrlParser::clParseURL::ParseURL(host);
71 int port; 71 int port{};
72 if (parsedUrl.m_Scheme == "http") { 72 if (parsedUrl.m_Scheme == "http") {
73 if (!parsedUrl.GetPort(&port)) { 73 if (!parsedUrl.GetPort(&port)) {
74 port = HTTP_PORT; 74 port = HTTP_PORT;
75 } 75 }
76 cli = std::make_unique<httplib::Client>(parsedUrl.m_Host.c_str(), port);
77 } else if (parsedUrl.m_Scheme == "https") { 76 } else if (parsedUrl.m_Scheme == "https") {
78 if (!parsedUrl.GetPort(&port)) { 77 if (!parsedUrl.GetPort(&port)) {
79 port = HTTPS_PORT; 78 port = HTTPS_PORT;
80 } 79 }
81 cli = std::make_unique<httplib::SSLClient>(parsedUrl.m_Host.c_str(), port);
82 } else { 80 } else {
83 LOG_ERROR(WebService, "Bad URL scheme {}", parsedUrl.m_Scheme); 81 LOG_ERROR(WebService, "Bad URL scheme {}", parsedUrl.m_Scheme);
84 return Common::WebResult{Common::WebResult::Code::InvalidURL, "Bad URL scheme", ""}; 82 return WebResult{WebResult::Code::InvalidURL, "Bad URL scheme", ""};
85 } 83 }
84 cli = std::make_unique<httplib::Client>(parsedUrl.m_Host.c_str(), port);
86 } 85 }
87 if (cli == nullptr) { 86 cli->set_connection_timeout(TIMEOUT_SECONDS);
88 LOG_ERROR(WebService, "Invalid URL {}", host + path); 87 cli->set_read_timeout(TIMEOUT_SECONDS);
89 return Common::WebResult{Common::WebResult::Code::InvalidURL, "Invalid URL", ""}; 88 cli->set_write_timeout(TIMEOUT_SECONDS);
90 }
91 cli->set_timeout_sec(TIMEOUT_SECONDS);
92 89
93 httplib::Headers params; 90 httplib::Headers params;
94 if (!jwt.empty()) { 91 if (!jwt.empty()) {
@@ -106,7 +103,7 @@ struct Client::Impl {
106 std::string(API_VERSION.begin(), API_VERSION.end())); 103 std::string(API_VERSION.begin(), API_VERSION.end()));
107 if (method != "GET") { 104 if (method != "GET") {
108 params.emplace(std::string("Content-Type"), std::string("application/json")); 105 params.emplace(std::string("Content-Type"), std::string("application/json"));
109 }; 106 }
110 107
111 httplib::Request request; 108 httplib::Request request;
112 request.method = method; 109 request.method = method;
@@ -118,29 +115,28 @@ struct Client::Impl {
118 115
119 if (!cli->send(request, response)) { 116 if (!cli->send(request, response)) {
120 LOG_ERROR(WebService, "{} to {} returned null", method, host + path); 117 LOG_ERROR(WebService, "{} to {} returned null", method, host + path);
121 return Common::WebResult{Common::WebResult::Code::LibError, "Null response", ""}; 118 return WebResult{WebResult::Code::LibError, "Null response", ""};
122 } 119 }
123 120
124 if (response.status >= 400) { 121 if (response.status >= 400) {
125 LOG_ERROR(WebService, "{} to {} returned error status code: {}", method, host + path, 122 LOG_ERROR(WebService, "{} to {} returned error status code: {}", method, host + path,
126 response.status); 123 response.status);
127 return Common::WebResult{Common::WebResult::Code::HttpError, 124 return WebResult{WebResult::Code::HttpError, std::to_string(response.status), ""};
128 std::to_string(response.status), ""};
129 } 125 }
130 126
131 auto content_type = response.headers.find("content-type"); 127 auto content_type = response.headers.find("content-type");
132 128
133 if (content_type == response.headers.end()) { 129 if (content_type == response.headers.end()) {
134 LOG_ERROR(WebService, "{} to {} returned no content", method, host + path); 130 LOG_ERROR(WebService, "{} to {} returned no content", method, host + path);
135 return Common::WebResult{Common::WebResult::Code::WrongContent, "", ""}; 131 return WebResult{WebResult::Code::WrongContent, "", ""};
136 } 132 }
137 133
138 if (content_type->second.find(accept) == std::string::npos) { 134 if (content_type->second.find(accept) == std::string::npos) {
139 LOG_ERROR(WebService, "{} to {} returned wrong content: {}", method, host + path, 135 LOG_ERROR(WebService, "{} to {} returned wrong content: {}", method, host + path,
140 content_type->second); 136 content_type->second);
141 return Common::WebResult{Common::WebResult::Code::WrongContent, "Wrong content", ""}; 137 return WebResult{WebResult::Code::WrongContent, "Wrong content", ""};
142 } 138 }
143 return Common::WebResult{Common::WebResult::Code::Success, "", response.body}; 139 return WebResult{WebResult::Code::Success, "", response.body};
144 } 140 }
145 141
146 // Retrieve a new JWT from given username and token 142 // Retrieve a new JWT from given username and token
@@ -150,7 +146,7 @@ struct Client::Impl {
150 } 146 }
151 147
152 auto result = GenericRequest("POST", "/jwt/internal", "", "text/html", "", username, token); 148 auto result = GenericRequest("POST", "/jwt/internal", "", "text/html", "", username, token);
153 if (result.result_code != Common::WebResult::Code::Success) { 149 if (result.result_code != WebResult::Code::Success) {
154 LOG_ERROR(WebService, "UpdateJWT failed"); 150 LOG_ERROR(WebService, "UpdateJWT failed");
155 } else { 151 } else {
156 std::lock_guard lock{jwt_cache.mutex}; 152 std::lock_guard lock{jwt_cache.mutex};
@@ -180,29 +176,28 @@ Client::Client(std::string host, std::string username, std::string token)
180 176
181Client::~Client() = default; 177Client::~Client() = default;
182 178
183Common::WebResult Client::PostJson(const std::string& path, const std::string& data, 179WebResult Client::PostJson(const std::string& path, const std::string& data, bool allow_anonymous) {
184 bool allow_anonymous) {
185 return impl->GenericRequest("POST", path, data, allow_anonymous, "application/json"); 180 return impl->GenericRequest("POST", path, data, allow_anonymous, "application/json");
186} 181}
187 182
188Common::WebResult Client::GetJson(const std::string& path, bool allow_anonymous) { 183WebResult Client::GetJson(const std::string& path, bool allow_anonymous) {
189 return impl->GenericRequest("GET", path, "", allow_anonymous, "application/json"); 184 return impl->GenericRequest("GET", path, "", allow_anonymous, "application/json");
190} 185}
191 186
192Common::WebResult Client::DeleteJson(const std::string& path, const std::string& data, 187WebResult Client::DeleteJson(const std::string& path, const std::string& data,
193 bool allow_anonymous) { 188 bool allow_anonymous) {
194 return impl->GenericRequest("DELETE", path, data, allow_anonymous, "application/json"); 189 return impl->GenericRequest("DELETE", path, data, allow_anonymous, "application/json");
195} 190}
196 191
197Common::WebResult Client::GetPlain(const std::string& path, bool allow_anonymous) { 192WebResult Client::GetPlain(const std::string& path, bool allow_anonymous) {
198 return impl->GenericRequest("GET", path, "", allow_anonymous, "text/plain"); 193 return impl->GenericRequest("GET", path, "", allow_anonymous, "text/plain");
199} 194}
200 195
201Common::WebResult Client::GetImage(const std::string& path, bool allow_anonymous) { 196WebResult Client::GetImage(const std::string& path, bool allow_anonymous) {
202 return impl->GenericRequest("GET", path, "", allow_anonymous, "image/png"); 197 return impl->GenericRequest("GET", path, "", allow_anonymous, "image/png");
203} 198}
204 199
205Common::WebResult Client::GetExternalJWT(const std::string& audience) { 200WebResult Client::GetExternalJWT(const std::string& audience) {
206 return impl->GenericRequest("POST", fmt::format("/jwt/external/{}", audience), "", false, 201 return impl->GenericRequest("POST", fmt::format("/jwt/external/{}", audience), "", false,
207 "text/html"); 202 "text/html");
208} 203}