diff --git a/src/client/http/PostData.h b/src/client/http/PostData.h new file mode 100644 index 000000000..20bf75525 --- /dev/null +++ b/src/client/http/PostData.h @@ -0,0 +1,11 @@ +#pragma once +#include "common/String.h" +#include +#include + +namespace http +{ + using StringData = ByteString; + using FormData = std::map; + using PostData = std::variant; +}; diff --git a/src/client/http/Request.cpp b/src/client/http/Request.cpp index 85266c132..88963b096 100644 --- a/src/client/http/Request.cpp +++ b/src/client/http/Request.cpp @@ -30,12 +30,12 @@ namespace http handle->headers.push_back(header); } - void Request::AddPostData(std::map data) + void Request::AddPostData(PostData data) { assert(handle->state == RequestHandle::ready); // Even if the map is empty, calling this function signifies you want to do a POST request handle->isPost = true; - handle->postData.insert(data.begin(), data.end()); + handle->postData = data; } void Request::AuthHeaders(ByteString ID, ByteString session) @@ -97,17 +97,17 @@ namespace http return { handle->statusCode, std::move(handle->responseData) }; } - std::pair Request::Simple(ByteString uri, std::map post_data) + std::pair Request::Simple(ByteString uri, FormData postData) { - return SimpleAuth(uri, "", "", post_data); + return SimpleAuth(uri, "", "", postData); } - std::pair Request::SimpleAuth(ByteString uri, ByteString ID, ByteString session, std::map post_data) + std::pair Request::SimpleAuth(ByteString uri, ByteString ID, ByteString session, FormData postData) { auto request = std::make_unique(uri); - if (!post_data.empty()) + if (!postData.empty()) { - request->AddPostData(post_data); + request->AddPostData(postData); } request->AuthHeaders(ID, session); request->Start(); diff --git a/src/client/http/Request.h b/src/client/http/Request.h index 0a6aff222..7906c1be1 100644 --- a/src/client/http/Request.h +++ b/src/client/http/Request.h @@ -1,5 +1,6 @@ #pragma once #include "common/String.h" +#include "PostData.h" #include #include #include @@ -22,7 +23,8 @@ namespace http void Verb(ByteString newVerb); void AddHeader(ByteString header); - void AddPostData(std::map data); + + void AddPostData(PostData data); void AuthHeaders(ByteString ID, ByteString session); void Start(); @@ -32,8 +34,8 @@ namespace http const std::vector &ResponseHeaders() const; std::pair Finish(); // status, data - static std::pair Simple(ByteString uri, std::map post_data = {}); - static std::pair SimpleAuth(ByteString uri, ByteString ID, ByteString session, std::map post_data = {}); + static std::pair Simple(ByteString uri, FormData postData = {}); + static std::pair SimpleAuth(ByteString uri, ByteString ID, ByteString session, FormData postData = {}); friend class RequestManager; }; diff --git a/src/client/http/SaveUserInfoRequest.cpp b/src/client/http/SaveUserInfoRequest.cpp index 509c48678..1a25478ac 100644 --- a/src/client/http/SaveUserInfoRequest.cpp +++ b/src/client/http/SaveUserInfoRequest.cpp @@ -7,7 +7,7 @@ namespace http SaveUserInfoRequest::SaveUserInfoRequest(UserInfo &info) : APIRequest(ByteString::Build(SCHEME, SERVER, "/Profile.json")) { - AddPostData({ + AddPostData(FormData{ { "Location", info.location.ToUtf8() }, { "Biography", info.biography.ToUtf8() } }); diff --git a/src/client/http/requestmanager/Libcurl.cpp b/src/client/http/requestmanager/Libcurl.cpp index 22a87dbb6..2ec9d1d05 100644 --- a/src/client/http/requestmanager/Libcurl.cpp +++ b/src/client/http/requestmanager/Libcurl.cpp @@ -163,9 +163,10 @@ namespace http handle->curlHeaders = newHeaders; } { - auto postData = handle->postData; - if (postData.size()) + auto &postData = handle->postData; + if (std::holds_alternative(postData) && std::get(postData).size()) { + auto &formData = std::get(postData); #ifdef REQUEST_USE_CURL_MIMEPOST handle->curlPostFields = curl_mime_init(handle->curlEasy); if (!handle->curlPostFields) @@ -173,7 +174,7 @@ namespace http // Hopefully this is what a NULL from curl_mime_init means. HandleCURLcode(CURLE_OUT_OF_MEMORY); } - for (auto &field : postData) + for (auto &field : formData) { curl_mimepart *part = curl_mime_addpart(handle->curlPostFields); if (!part) @@ -194,7 +195,7 @@ namespace http } HandleCURLcode(curl_easy_setopt(handle->curlEasy, CURLOPT_MIMEPOST, handle->curlPostFields)); #else - for (auto &field : postData) + for (auto &field : formData) { if (auto split = field.first.SplitBy(':')) { @@ -217,6 +218,12 @@ namespace http HandleCURLcode(curl_easy_setopt(handle->curlEasy, CURLOPT_HTTPPOST, handle->curlPostFieldsFirst)); #endif } + else if (std::holds_alternative(postData) && std::get(postData).size()) + { + auto &stringData = std::get(postData); + HandleCURLcode(curl_easy_setopt(handle->curlEasy, CURLOPT_POSTFIELDS, &stringData[0])); + HandleCURLcode(curl_easy_setopt(handle->curlEasy, CURLOPT_POSTFIELDSIZE_LARGE, curl_off_t(stringData.size()))); + } else if (handle->isPost) { HandleCURLcode(curl_easy_setopt(handle->curlEasy, CURLOPT_POST, 1L)); diff --git a/src/client/http/requestmanager/RequestManager.h b/src/client/http/requestmanager/RequestManager.h index b199e1a92..1342138ef 100644 --- a/src/client/http/requestmanager/RequestManager.h +++ b/src/client/http/requestmanager/RequestManager.h @@ -1,12 +1,12 @@ #pragma once #include "common/ExplicitSingleton.h" #include "common/String.h" +#include "client/http/PostData.h" #include #include #include #include #include -#include #include namespace http @@ -24,7 +24,7 @@ namespace http ByteString uri; ByteString verb; bool isPost = false; - std::map postData; + PostData postData; std::vector headers; enum State diff --git a/src/lua/LuaHttp.cpp b/src/lua/LuaHttp.cpp index 482b479eb..fb966c9bd 100644 --- a/src/lua/LuaHttp.cpp +++ b/src/lua/LuaHttp.cpp @@ -46,7 +46,7 @@ private: } public: - static int Make(lua_State *l, const ByteString &uri, bool isPost, const ByteString &verb, RequestType type, const std::map &post_data, const std::vector &headers) + static int Make(lua_State *l, const ByteString &uri, bool isPost, const ByteString &verb, RequestType type, const http::PostData &postData, const std::vector &headers) { auto authUser = Client::Ref().GetAuthUser(); if (type == getAuthToken && !authUser.UserID) @@ -73,7 +73,7 @@ public: } if (isPost) { - rh->request->AddPostData(post_data); + rh->request->AddPostData(postData); } if (type == getAuthToken) { @@ -220,7 +220,7 @@ static int http_request_finish(lua_State *l) static int http_request(lua_State *l, bool isPost) { ByteString uri = tpt_lua_checkByteString(l, 1); - std::map post_data; + http::PostData postData; auto headersIndex = 2; auto verbIndex = 3; @@ -228,13 +228,19 @@ static int http_request(lua_State *l, bool isPost) { headersIndex += 1; verbIndex += 1; - if (lua_istable(l, 2)) + if (lua_isstring(l, 2)) { + postData = tpt_lua_toByteString(l, 2); + } + else if (lua_istable(l, 2)) + { + postData = http::FormData{}; + auto &formData = std::get(postData); lua_pushnil(l); while (lua_next(l, 2)) { lua_pushvalue(l, -2); - post_data.emplace(tpt_lua_toByteString(l, -1), tpt_lua_toByteString(l, -2)); + formData.emplace(tpt_lua_toByteString(l, -1), tpt_lua_toByteString(l, -2)); lua_pop(l, 2); } } @@ -267,7 +273,7 @@ static int http_request(lua_State *l, bool isPost) } auto verb = tpt_lua_optByteString(l, verbIndex, ""); - return RequestHandle::Make(l, uri, isPost, verb, RequestHandle::normal, post_data, headers); + return RequestHandle::Make(l, uri, isPost, verb, RequestHandle::normal, postData, headers); } static int http_get_auth_token(lua_State *l)