mirror of
https://github.com/minetest/minetest.git
synced 2024-11-27 01:53:45 +01:00
Add PUT and DELETE request + specific method value to HTTP API (#9909)
This commit is contained in:
parent
f34abaedd2
commit
715a123a33
@ -8071,11 +8071,13 @@ Used by `HTTPApiTable.fetch` and `HTTPApiTable.fetch_async`.
|
||||
timeout = 10,
|
||||
-- Timeout for connection in seconds. Default is 3 seconds.
|
||||
|
||||
post_data = "Raw POST request data string" OR {field1 = "data1", field2 = "data2"},
|
||||
-- Optional, if specified a POST request with post_data is performed.
|
||||
method = "GET", "POST", "PUT" or "DELETE"
|
||||
-- The http method to use. Defaults to "GET".
|
||||
|
||||
data = "Raw request data string" OR {field1 = "data1", field2 = "data2"},
|
||||
-- Data for the POST, PUT or DELETE request.
|
||||
-- Accepts both a string and a table. If a table is specified, encodes
|
||||
-- table as x-www-form-urlencoded key-value pairs.
|
||||
-- If post_data is not specified, a GET request is performed instead.
|
||||
|
||||
user_agent = "ExampleUserAgent",
|
||||
-- Optional, if specified replaces the default minetest user agent with
|
||||
@ -8089,6 +8091,10 @@ Used by `HTTPApiTable.fetch` and `HTTPApiTable.fetch_async`.
|
||||
multipart = boolean
|
||||
-- Optional, if true performs a multipart HTTP request.
|
||||
-- Default is false.
|
||||
-- Post only, data must be array
|
||||
|
||||
post_data = "Raw POST request data string" OR {field1 = "data1", field2 = "data2"},
|
||||
-- Deprecated, use `data` instead. Forces `method = "POST"`.
|
||||
}
|
||||
|
||||
`HTTPRequestResult` definition
|
||||
|
@ -260,7 +260,8 @@ void ClientMediaDownloader::initialStep(Client *client)
|
||||
fetch_request.request_id = m_httpfetch_next_id; // == i
|
||||
fetch_request.timeout = m_httpfetch_timeout;
|
||||
fetch_request.connect_timeout = m_httpfetch_timeout;
|
||||
fetch_request.post_data = required_hash_set;
|
||||
fetch_request.method = HTTP_POST;
|
||||
fetch_request.raw_data = required_hash_set;
|
||||
fetch_request.extra_headers.emplace_back(
|
||||
"Content-Type: application/octet-stream");
|
||||
|
||||
|
@ -294,13 +294,11 @@ HTTPFetchOngoing::HTTPFetchOngoing(const HTTPFetchRequest &request_,
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &oss);
|
||||
}
|
||||
|
||||
// Set POST (or GET) data
|
||||
if (request.post_fields.empty() && request.post_data.empty()) {
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
|
||||
} else if (request.multipart) {
|
||||
// Set data from fields or raw_data
|
||||
if (request.multipart) {
|
||||
curl_httppost *last = NULL;
|
||||
for (StringMap::iterator it = request.post_fields.begin();
|
||||
it != request.post_fields.end(); ++it) {
|
||||
for (StringMap::iterator it = request.fields.begin();
|
||||
it != request.fields.end(); ++it) {
|
||||
curl_formadd(&post, &last,
|
||||
CURLFORM_NAMELENGTH, it->first.size(),
|
||||
CURLFORM_PTRNAME, it->first.c_str(),
|
||||
@ -311,28 +309,42 @@ HTTPFetchOngoing::HTTPFetchOngoing(const HTTPFetchRequest &request_,
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
|
||||
// request.post_fields must now *never* be
|
||||
// modified until CURLOPT_HTTPPOST is cleared
|
||||
} else if (request.post_data.empty()) {
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||
std::string str;
|
||||
for (auto &post_field : request.post_fields) {
|
||||
if (!str.empty())
|
||||
str += "&";
|
||||
str += urlencode(post_field.first);
|
||||
str += "=";
|
||||
str += urlencode(post_field.second);
|
||||
}
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE,
|
||||
str.size());
|
||||
curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS,
|
||||
str.c_str());
|
||||
} else {
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE,
|
||||
request.post_data.size());
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS,
|
||||
request.post_data.c_str());
|
||||
// request.post_data must now *never* be
|
||||
// modified until CURLOPT_POSTFIELDS is cleared
|
||||
switch (request.method) {
|
||||
case HTTP_GET:
|
||||
curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
|
||||
break;
|
||||
case HTTP_POST:
|
||||
curl_easy_setopt(curl, CURLOPT_POST, 1);
|
||||
break;
|
||||
case HTTP_PUT:
|
||||
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
|
||||
break;
|
||||
case HTTP_DELETE:
|
||||
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
|
||||
break;
|
||||
}
|
||||
if (request.method != HTTP_GET) {
|
||||
if (!request.raw_data.empty()) {
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE,
|
||||
request.raw_data.size());
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS,
|
||||
request.raw_data.c_str());
|
||||
} else if (!request.fields.empty()) {
|
||||
std::string str;
|
||||
for (auto &field : request.fields) {
|
||||
if (!str.empty())
|
||||
str += "&";
|
||||
str += urlencode(field.first);
|
||||
str += "=";
|
||||
str += urlencode(field.second);
|
||||
}
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE,
|
||||
str.size());
|
||||
curl_easy_setopt(curl, CURLOPT_COPYPOSTFIELDS,
|
||||
str.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set additional HTTP headers
|
||||
for (const std::string &extra_header : request.extra_headers) {
|
||||
|
@ -28,6 +28,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define HTTPFETCH_DISCARD 0
|
||||
#define HTTPFETCH_SYNC 1
|
||||
|
||||
// Methods
|
||||
enum HttpMethod : u8
|
||||
{
|
||||
HTTP_GET,
|
||||
HTTP_POST,
|
||||
HTTP_PUT,
|
||||
HTTP_DELETE,
|
||||
};
|
||||
|
||||
struct HTTPFetchRequest
|
||||
{
|
||||
std::string url = "";
|
||||
@ -50,12 +59,15 @@ struct HTTPFetchRequest
|
||||
// application/x-www-form-urlencoded. POST-only.
|
||||
bool multipart = false;
|
||||
|
||||
// POST fields. Fields are escaped properly.
|
||||
// If this is empty a GET request is done instead.
|
||||
StringMap post_fields;
|
||||
// The Method to use default = GET
|
||||
// Avaible methods GET, POST, PUT, DELETE
|
||||
HttpMethod method = HTTP_GET;
|
||||
|
||||
// Raw POST data, overrides post_fields.
|
||||
std::string post_data;
|
||||
// Fields of the request
|
||||
StringMap fields;
|
||||
|
||||
// Raw data of the request overrides fields
|
||||
std::string raw_data;
|
||||
|
||||
// If not empty, should contain entries such as "Accept: text/html"
|
||||
std::vector<std::string> extra_headers;
|
||||
|
@ -1034,7 +1034,7 @@ const static std::string accessDeniedStrings[SERVER_ACCESSDENIED_MAX] = {
|
||||
"This server has experienced an internal error. You will now be disconnected."
|
||||
};
|
||||
|
||||
enum PlayerListModifer: u8
|
||||
enum PlayerListModifer : u8
|
||||
{
|
||||
PLAYER_LIST_INIT,
|
||||
PLAYER_LIST_ADD,
|
||||
|
@ -49,17 +49,40 @@ void ModApiHttp::read_http_fetch_request(lua_State *L, HTTPFetchRequest &req)
|
||||
req.multipart = getboolfield_default(L, 1, "multipart", false);
|
||||
req.timeout = getintfield_default(L, 1, "timeout", 3) * 1000;
|
||||
|
||||
// post_data: if table, post form data, otherwise raw data
|
||||
lua_getfield(L, 1, "method");
|
||||
if (lua_isstring(L, -1)) {
|
||||
std::string mth = getstringfield_default(L, 1, "method", "");
|
||||
if (mth == "GET")
|
||||
req.method = HTTP_GET;
|
||||
else if (mth == "POST")
|
||||
req.method = HTTP_POST;
|
||||
else if (mth == "PUT")
|
||||
req.method = HTTP_PUT;
|
||||
else if (mth == "DELETE")
|
||||
req.method = HTTP_DELETE;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
// post_data: if table, post form data, otherwise raw data DEPRECATED use data and method instead
|
||||
lua_getfield(L, 1, "post_data");
|
||||
if (lua_isnil(L, 2)) {
|
||||
lua_pop(L, 1);
|
||||
lua_getfield(L, 1, "data");
|
||||
}
|
||||
else {
|
||||
req.method = HTTP_POST;
|
||||
}
|
||||
|
||||
if (lua_istable(L, 2)) {
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, 2) != 0) {
|
||||
req.post_fields[readParam<std::string>(L, -2)] = readParam<std::string>(L, -1);
|
||||
req.fields[readParam<std::string>(L, -2)] = readParam<std::string>(L, -1);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
} else if (lua_isstring(L, 2)) {
|
||||
req.post_data = readParam<std::string>(L, 2);
|
||||
req.raw_data = readParam<std::string>(L, 2);
|
||||
}
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_getfield(L, 1, "extra_headers");
|
||||
|
@ -32,10 +32,10 @@ private:
|
||||
static void read_http_fetch_request(lua_State *L, HTTPFetchRequest &req);
|
||||
static void push_http_fetch_result(lua_State *L, HTTPFetchResult &res, bool completed = true);
|
||||
|
||||
// http_fetch_sync({url=, timeout=, post_data=})
|
||||
// http_fetch_sync({url=, timeout=, data=})
|
||||
static int l_http_fetch_sync(lua_State *L);
|
||||
|
||||
// http_fetch_async({url=, timeout=, post_data=})
|
||||
// http_fetch_async({url=, timeout=, data=})
|
||||
static int l_http_fetch_async(lua_State *L);
|
||||
|
||||
// http_fetch_async_get(handle)
|
||||
|
@ -261,11 +261,11 @@ void sendAnnounce(AnnounceAction action,
|
||||
|
||||
HTTPFetchRequest fetch_request;
|
||||
fetch_request.url = g_settings->get("serverlist_url") + std::string("/announce");
|
||||
fetch_request.post_fields["json"] = fastWriteJson(server);
|
||||
fetch_request.method = HTTP_POST;
|
||||
fetch_request.fields["json"] = fastWriteJson(server);
|
||||
fetch_request.multipart = true;
|
||||
httpfetch_async(fetch_request);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ServerList
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user