summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2019-11-09 03:09:39 -0500
committerGravatar bunnei2019-11-09 14:00:44 -0500
commit8dc9f35baf7e0338ae611a95c11b628e8edc00dd (patch)
tree9d8795e81c2c029a475da39758fb8a36ff3dd4f9
parentyuzu: configure_web: Use Base64 encoded token for simplifying user experience. (diff)
downloadyuzu-8dc9f35baf7e0338ae611a95c11b628e8edc00dd.tar.gz
yuzu-8dc9f35baf7e0338ae611a95c11b628e8edc00dd.tar.xz
yuzu-8dc9f35baf7e0338ae611a95c11b628e8edc00dd.zip
web-service: Port citra's updated web_backend code.
-rw-r--r--src/web_service/web_backend.cpp52
-rw-r--r--src/web_service/web_backend.h23
2 files changed, 57 insertions, 18 deletions
diff --git a/src/web_service/web_backend.cpp b/src/web_service/web_backend.cpp
index dc149d2ed..6683f459f 100644
--- a/src/web_service/web_backend.cpp
+++ b/src/web_service/web_backend.cpp
@@ -2,10 +2,12 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <array>
5#include <cstdlib> 6#include <cstdlib>
6#include <mutex> 7#include <mutex>
7#include <string> 8#include <string>
8#include <LUrlParser.h> 9#include <LUrlParser.h>
10#include <fmt/format.h>
9#include <httplib.h> 11#include <httplib.h>
10#include "common/common_types.h" 12#include "common/common_types.h"
11#include "common/logging/log.h" 13#include "common/logging/log.h"
@@ -16,10 +18,10 @@ namespace WebService {
16 18
17constexpr std::array<const char, 1> API_VERSION{'1'}; 19constexpr std::array<const char, 1> API_VERSION{'1'};
18 20
19constexpr u32 HTTP_PORT = 80; 21constexpr int HTTP_PORT = 80;
20constexpr u32 HTTPS_PORT = 443; 22constexpr int HTTPS_PORT = 443;
21 23
22constexpr u32 TIMEOUT_SECONDS = 30; 24constexpr std::size_t TIMEOUT_SECONDS = 30;
23 25
24struct Client::Impl { 26struct Client::Impl {
25 Impl(std::string host, std::string username, std::string token) 27 Impl(std::string host, std::string username, std::string token)
@@ -31,8 +33,9 @@ struct Client::Impl {
31 } 33 }
32 34
33 /// A generic function handles POST, GET and DELETE request together 35 /// A generic function handles POST, GET and DELETE request together
34 Common::WebResult GenericJson(const std::string& method, const std::string& path, 36 Common::WebResult GenericRequest(const std::string& method, const std::string& path,
35 const std::string& data, bool allow_anonymous) { 37 const std::string& data, bool allow_anonymous,
38 const std::string& accept) {
36 if (jwt.empty()) { 39 if (jwt.empty()) {
37 UpdateJWT(); 40 UpdateJWT();
38 } 41 }
@@ -43,11 +46,11 @@ struct Client::Impl {
43 "Credentials needed"}; 46 "Credentials needed"};
44 } 47 }
45 48
46 auto result = GenericJson(method, path, data, jwt); 49 auto result = GenericRequest(method, path, data, accept, jwt);
47 if (result.result_string == "401") { 50 if (result.result_string == "401") {
48 // Try again with new JWT 51 // Try again with new JWT
49 UpdateJWT(); 52 UpdateJWT();
50 result = GenericJson(method, path, data, jwt); 53 result = GenericRequest(method, path, data, accept, jwt);
51 } 54 }
52 55
53 return result; 56 return result;
@@ -56,12 +59,13 @@ struct Client::Impl {
56 /** 59 /**
57 * A generic function with explicit authentication method specified 60 * A generic function with explicit authentication method specified
58 * JWT is used if the jwt parameter is not empty 61 * JWT is used if the jwt parameter is not empty
59 * username + token is used if jwt is empty but username and token are not empty 62 * username + token is used if jwt is empty but username and token are
60 * anonymous if all of jwt, username and token are empty 63 * not empty anonymous if all of jwt, username and token are empty
61 */ 64 */
62 Common::WebResult GenericJson(const std::string& method, const std::string& path, 65 Common::WebResult GenericRequest(const std::string& method, const std::string& path,
63 const std::string& data, const std::string& jwt = "", 66 const std::string& data, const std::string& accept,
64 const std::string& username = "", const std::string& token = "") { 67 const std::string& jwt = "", const std::string& username = "",
68 const std::string& token = "") {
65 if (cli == nullptr) { 69 if (cli == nullptr) {
66 auto parsedUrl = LUrlParser::clParseURL::ParseURL(host); 70 auto parsedUrl = LUrlParser::clParseURL::ParseURL(host);
67 int port; 71 int port;
@@ -132,8 +136,7 @@ struct Client::Impl {
132 return Common::WebResult{Common::WebResult::Code::WrongContent, ""}; 136 return Common::WebResult{Common::WebResult::Code::WrongContent, ""};
133 } 137 }
134 138
135 if (content_type->second.find("application/json") == std::string::npos && 139 if (content_type->second.find(accept) == std::string::npos) {
136 content_type->second.find("text/html; charset=utf-8") == std::string::npos) {
137 LOG_ERROR(WebService, "{} to {} returned wrong content: {}", method, host + path, 140 LOG_ERROR(WebService, "{} to {} returned wrong content: {}", method, host + path,
138 content_type->second); 141 content_type->second);
139 return Common::WebResult{Common::WebResult::Code::WrongContent, "Wrong content"}; 142 return Common::WebResult{Common::WebResult::Code::WrongContent, "Wrong content"};
@@ -147,7 +150,7 @@ struct Client::Impl {
147 return; 150 return;
148 } 151 }
149 152
150 auto result = GenericJson("POST", "/jwt/internal", "", "", username, token); 153 auto result = GenericRequest("POST", "/jwt/internal", "", "text/html", "", username, token);
151 if (result.result_code != Common::WebResult::Code::Success) { 154 if (result.result_code != Common::WebResult::Code::Success) {
152 LOG_ERROR(WebService, "UpdateJWT failed"); 155 LOG_ERROR(WebService, "UpdateJWT failed");
153 } else { 156 } else {
@@ -180,16 +183,29 @@ Client::~Client() = default;
180 183
181Common::WebResult Client::PostJson(const std::string& path, const std::string& data, 184Common::WebResult Client::PostJson(const std::string& path, const std::string& data,
182 bool allow_anonymous) { 185 bool allow_anonymous) {
183 return impl->GenericJson("POST", path, data, allow_anonymous); 186 return impl->GenericRequest("POST", path, data, allow_anonymous, "application/json");
184} 187}
185 188
186Common::WebResult Client::GetJson(const std::string& path, bool allow_anonymous) { 189Common::WebResult Client::GetJson(const std::string& path, bool allow_anonymous) {
187 return impl->GenericJson("GET", path, "", allow_anonymous); 190 return impl->GenericRequest("GET", path, "", allow_anonymous, "application/json");
188} 191}
189 192
190Common::WebResult Client::DeleteJson(const std::string& path, const std::string& data, 193Common::WebResult Client::DeleteJson(const std::string& path, const std::string& data,
191 bool allow_anonymous) { 194 bool allow_anonymous) {
192 return impl->GenericJson("DELETE", path, data, allow_anonymous); 195 return impl->GenericRequest("DELETE", path, data, allow_anonymous, "application/json");
196}
197
198Common::WebResult Client::GetPlain(const std::string& path, bool allow_anonymous) {
199 return impl->GenericRequest("GET", path, "", allow_anonymous, "text/plain");
200}
201
202Common::WebResult Client::GetImage(const std::string& path, bool allow_anonymous) {
203 return impl->GenericRequest("GET", path, "", allow_anonymous, "image/png");
204}
205
206Common::WebResult Client::GetExternalJWT(const std::string& audience) {
207 return impl->GenericRequest("POST", fmt::format("/jwt/external/{}", audience), "", false,
208 "text/html");
193} 209}
194 210
195} // namespace WebService 211} // namespace WebService
diff --git a/src/web_service/web_backend.h b/src/web_service/web_backend.h
index c637e09df..04121f17e 100644
--- a/src/web_service/web_backend.h
+++ b/src/web_service/web_backend.h
@@ -46,6 +46,29 @@ public:
46 Common::WebResult DeleteJson(const std::string& path, const std::string& data, 46 Common::WebResult DeleteJson(const std::string& path, const std::string& data,
47 bool allow_anonymous); 47 bool allow_anonymous);
48 48
49 /**
50 * Gets a plain string from the specified path.
51 * @param path the URL segment after the host address.
52 * @param allow_anonymous If true, allow anonymous unauthenticated requests.
53 * @return the result of the request.
54 */
55 Common::WebResult GetPlain(const std::string& path, bool allow_anonymous);
56
57 /**
58 * Gets an PNG image from the specified path.
59 * @param path the URL segment after the host address.
60 * @param allow_anonymous If true, allow anonymous unauthenticated requests.
61 * @return the result of the request.
62 */
63 Common::WebResult GetImage(const std::string& path, bool allow_anonymous);
64
65 /**
66 * Requests an external JWT for the specific audience provided.
67 * @param audience the audience of the JWT requested.
68 * @return the result of the request.
69 */
70 Common::WebResult GetExternalJWT(const std::string& audience);
71
49private: 72private:
50 struct Impl; 73 struct Impl;
51 std::unique_ptr<Impl> impl; 74 std::unique_ptr<Impl> impl;