Enable non-multipart POST requests

This commit is contained in:
Tamás Bálint Misius 2023-02-12 20:18:34 +01:00
parent 6179071351
commit 7cd88a094c
No known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2
7 changed files with 49 additions and 23 deletions

View File

@ -0,0 +1,11 @@
#pragma once
#include "common/String.h"
#include <map>
#include <variant>
namespace http
{
using StringData = ByteString;
using FormData = std::map<ByteString, ByteString>;
using PostData = std::variant<StringData, FormData>;
};

View File

@ -30,12 +30,12 @@ namespace http
handle->headers.push_back(header); handle->headers.push_back(header);
} }
void Request::AddPostData(std::map<ByteString, ByteString> data) void Request::AddPostData(PostData data)
{ {
assert(handle->state == RequestHandle::ready); assert(handle->state == RequestHandle::ready);
// Even if the map is empty, calling this function signifies you want to do a POST request // Even if the map is empty, calling this function signifies you want to do a POST request
handle->isPost = true; handle->isPost = true;
handle->postData.insert(data.begin(), data.end()); handle->postData = data;
} }
void Request::AuthHeaders(ByteString ID, ByteString session) void Request::AuthHeaders(ByteString ID, ByteString session)
@ -97,17 +97,17 @@ namespace http
return { handle->statusCode, std::move(handle->responseData) }; return { handle->statusCode, std::move(handle->responseData) };
} }
std::pair<int, ByteString> Request::Simple(ByteString uri, std::map<ByteString, ByteString> post_data) std::pair<int, ByteString> Request::Simple(ByteString uri, FormData postData)
{ {
return SimpleAuth(uri, "", "", post_data); return SimpleAuth(uri, "", "", postData);
} }
std::pair<int, ByteString> Request::SimpleAuth(ByteString uri, ByteString ID, ByteString session, std::map<ByteString, ByteString> post_data) std::pair<int, ByteString> Request::SimpleAuth(ByteString uri, ByteString ID, ByteString session, FormData postData)
{ {
auto request = std::make_unique<Request>(uri); auto request = std::make_unique<Request>(uri);
if (!post_data.empty()) if (!postData.empty())
{ {
request->AddPostData(post_data); request->AddPostData(postData);
} }
request->AuthHeaders(ID, session); request->AuthHeaders(ID, session);
request->Start(); request->Start();

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "common/String.h" #include "common/String.h"
#include "PostData.h"
#include <map> #include <map>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -22,7 +23,8 @@ namespace http
void Verb(ByteString newVerb); void Verb(ByteString newVerb);
void AddHeader(ByteString header); void AddHeader(ByteString header);
void AddPostData(std::map<ByteString, ByteString> data);
void AddPostData(PostData data);
void AuthHeaders(ByteString ID, ByteString session); void AuthHeaders(ByteString ID, ByteString session);
void Start(); void Start();
@ -32,8 +34,8 @@ namespace http
const std::vector<ByteString> &ResponseHeaders() const; const std::vector<ByteString> &ResponseHeaders() const;
std::pair<int, ByteString> Finish(); // status, data std::pair<int, ByteString> Finish(); // status, data
static std::pair<int, ByteString> Simple(ByteString uri, std::map<ByteString, ByteString> post_data = {}); static std::pair<int, ByteString> Simple(ByteString uri, FormData postData = {});
static std::pair<int, ByteString> SimpleAuth(ByteString uri, ByteString ID, ByteString session, std::map<ByteString, ByteString> post_data = {}); static std::pair<int, ByteString> SimpleAuth(ByteString uri, ByteString ID, ByteString session, FormData postData = {});
friend class RequestManager; friend class RequestManager;
}; };

View File

@ -7,7 +7,7 @@ namespace http
SaveUserInfoRequest::SaveUserInfoRequest(UserInfo &info) : SaveUserInfoRequest::SaveUserInfoRequest(UserInfo &info) :
APIRequest(ByteString::Build(SCHEME, SERVER, "/Profile.json")) APIRequest(ByteString::Build(SCHEME, SERVER, "/Profile.json"))
{ {
AddPostData({ AddPostData(FormData{
{ "Location", info.location.ToUtf8() }, { "Location", info.location.ToUtf8() },
{ "Biography", info.biography.ToUtf8() } { "Biography", info.biography.ToUtf8() }
}); });

View File

@ -163,9 +163,10 @@ namespace http
handle->curlHeaders = newHeaders; handle->curlHeaders = newHeaders;
} }
{ {
auto postData = handle->postData; auto &postData = handle->postData;
if (postData.size()) if (std::holds_alternative<http::FormData>(postData) && std::get<http::FormData>(postData).size())
{ {
auto &formData = std::get<http::FormData>(postData);
#ifdef REQUEST_USE_CURL_MIMEPOST #ifdef REQUEST_USE_CURL_MIMEPOST
handle->curlPostFields = curl_mime_init(handle->curlEasy); handle->curlPostFields = curl_mime_init(handle->curlEasy);
if (!handle->curlPostFields) if (!handle->curlPostFields)
@ -173,7 +174,7 @@ namespace http
// Hopefully this is what a NULL from curl_mime_init means. // Hopefully this is what a NULL from curl_mime_init means.
HandleCURLcode(CURLE_OUT_OF_MEMORY); HandleCURLcode(CURLE_OUT_OF_MEMORY);
} }
for (auto &field : postData) for (auto &field : formData)
{ {
curl_mimepart *part = curl_mime_addpart(handle->curlPostFields); curl_mimepart *part = curl_mime_addpart(handle->curlPostFields);
if (!part) if (!part)
@ -194,7 +195,7 @@ namespace http
} }
HandleCURLcode(curl_easy_setopt(handle->curlEasy, CURLOPT_MIMEPOST, handle->curlPostFields)); HandleCURLcode(curl_easy_setopt(handle->curlEasy, CURLOPT_MIMEPOST, handle->curlPostFields));
#else #else
for (auto &field : postData) for (auto &field : formData)
{ {
if (auto split = field.first.SplitBy(':')) if (auto split = field.first.SplitBy(':'))
{ {
@ -217,6 +218,12 @@ namespace http
HandleCURLcode(curl_easy_setopt(handle->curlEasy, CURLOPT_HTTPPOST, handle->curlPostFieldsFirst)); HandleCURLcode(curl_easy_setopt(handle->curlEasy, CURLOPT_HTTPPOST, handle->curlPostFieldsFirst));
#endif #endif
} }
else if (std::holds_alternative<http::StringData>(postData) && std::get<http::StringData>(postData).size())
{
auto &stringData = std::get<http::StringData>(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) else if (handle->isPost)
{ {
HandleCURLcode(curl_easy_setopt(handle->curlEasy, CURLOPT_POST, 1L)); HandleCURLcode(curl_easy_setopt(handle->curlEasy, CURLOPT_POST, 1L));

View File

@ -1,12 +1,12 @@
#pragma once #pragma once
#include "common/ExplicitSingleton.h" #include "common/ExplicitSingleton.h"
#include "common/String.h" #include "common/String.h"
#include "client/http/PostData.h"
#include <atomic> #include <atomic>
#include <thread> #include <thread>
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <map>
#include <condition_variable> #include <condition_variable>
namespace http namespace http
@ -24,7 +24,7 @@ namespace http
ByteString uri; ByteString uri;
ByteString verb; ByteString verb;
bool isPost = false; bool isPost = false;
std::map<ByteString, ByteString> postData; PostData postData;
std::vector<ByteString> headers; std::vector<ByteString> headers;
enum State enum State

View File

@ -46,7 +46,7 @@ private:
} }
public: public:
static int Make(lua_State *l, const ByteString &uri, bool isPost, const ByteString &verb, RequestType type, const std::map<ByteString, ByteString> &post_data, const std::vector<ByteString> &headers) static int Make(lua_State *l, const ByteString &uri, bool isPost, const ByteString &verb, RequestType type, const http::PostData &postData, const std::vector<ByteString> &headers)
{ {
auto authUser = Client::Ref().GetAuthUser(); auto authUser = Client::Ref().GetAuthUser();
if (type == getAuthToken && !authUser.UserID) if (type == getAuthToken && !authUser.UserID)
@ -73,7 +73,7 @@ public:
} }
if (isPost) if (isPost)
{ {
rh->request->AddPostData(post_data); rh->request->AddPostData(postData);
} }
if (type == getAuthToken) if (type == getAuthToken)
{ {
@ -220,7 +220,7 @@ static int http_request_finish(lua_State *l)
static int http_request(lua_State *l, bool isPost) static int http_request(lua_State *l, bool isPost)
{ {
ByteString uri = tpt_lua_checkByteString(l, 1); ByteString uri = tpt_lua_checkByteString(l, 1);
std::map<ByteString, ByteString> post_data; http::PostData postData;
auto headersIndex = 2; auto headersIndex = 2;
auto verbIndex = 3; auto verbIndex = 3;
@ -228,13 +228,19 @@ static int http_request(lua_State *l, bool isPost)
{ {
headersIndex += 1; headersIndex += 1;
verbIndex += 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<http::FormData>(postData);
lua_pushnil(l); lua_pushnil(l);
while (lua_next(l, 2)) while (lua_next(l, 2))
{ {
lua_pushvalue(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); lua_pop(l, 2);
} }
} }
@ -267,7 +273,7 @@ static int http_request(lua_State *l, bool isPost)
} }
auto verb = tpt_lua_optByteString(l, verbIndex, ""); 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) static int http_get_auth_token(lua_State *l)