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);
}
void Request::AddPostData(std::map<ByteString, ByteString> 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<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);
if (!post_data.empty())
if (!postData.empty())
{
request->AddPostData(post_data);
request->AddPostData(postData);
}
request->AuthHeaders(ID, session);
request->Start();

View File

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

View File

@ -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() }
});

View File

@ -163,9 +163,10 @@ namespace http
handle->curlHeaders = newHeaders;
}
{
auto postData = handle->postData;
if (postData.size())
auto &postData = handle->postData;
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
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<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)
{
HandleCURLcode(curl_easy_setopt(handle->curlEasy, CURLOPT_POST, 1L));

View File

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

View File

@ -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<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();
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<ByteString, ByteString> 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<http::FormData>(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)