aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLejo <Lejo_1@web.de>2020-07-30 00:16:21 +0300
committerGitHub <noreply@github.com>2020-07-29 23:16:21 +0200
commit715a123a33db7b0f191259ba68cbc9c565d0d4e8 (patch)
tree5925cc93ad339477d58dcea42bcf79b62e2ded5d
parentf34abaedd2b9277c1862cd9b82ca3338747f104e (diff)
downloadminetest-715a123a33db7b0f191259ba68cbc9c565d0d4e8.tar.gz
minetest-715a123a33db7b0f191259ba68cbc9c565d0d4e8.tar.bz2
minetest-715a123a33db7b0f191259ba68cbc9c565d0d4e8.zip
Add PUT and DELETE request + specific method value to HTTP API (#9909)
-rw-r--r--doc/lua_api.txt12
-rw-r--r--src/client/clientmedia.cpp3
-rw-r--r--src/httpfetch.cpp66
-rw-r--r--src/httpfetch.h22
-rw-r--r--src/network/networkprotocol.h2
-rw-r--r--src/script/lua_api/l_http.cpp29
-rw-r--r--src/script/lua_api/l_http.h4
-rw-r--r--src/serverlist.cpp4
8 files changed, 98 insertions, 44 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index 5fe02b452..2d22dc899 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -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
diff --git a/src/client/clientmedia.cpp b/src/client/clientmedia.cpp
index 8cd3b6bcc..c4c08c05d 100644
--- a/src/client/clientmedia.cpp
+++ b/src/client/clientmedia.cpp
@@ -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");
diff --git a/src/httpfetch.cpp b/src/httpfetch.cpp
index 326b5052f..65202ce3e 100644
--- a/src/httpfetch.cpp
+++ b/src/httpfetch.cpp
@@ -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) {
diff --git a/src/httpfetch.h b/src/httpfetch.h
index ae8b5afb5..3b9f17f0a 100644
--- a/src/httpfetch.h
+++ b/src/httpfetch.h
@@ -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;
+
+ // Fields of the request
+ StringMap fields;
- // Raw POST data, overrides post_fields.
- std::string post_data;
+ // 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;
diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h
index 28abf02c0..05600cda9 100644
--- a/src/network/networkprotocol.h
+++ b/src/network/networkprotocol.h
@@ -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,
diff --git a/src/script/lua_api/l_http.cpp b/src/script/lua_api/l_http.cpp
index ec43bf174..5ea3b3f99 100644
--- a/src/script/lua_api/l_http.cpp
+++ b/src/script/lua_api/l_http.cpp
@@ -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");
diff --git a/src/script/lua_api/l_http.h b/src/script/lua_api/l_http.h
index de6e51b37..c3a2a5276 100644
--- a/src/script/lua_api/l_http.h
+++ b/src/script/lua_api/l_http.h
@@ -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)
diff --git a/src/serverlist.cpp b/src/serverlist.cpp
index 18264e933..2f6ab2e61 100644
--- a/src/serverlist.cpp
+++ b/src/serverlist.cpp
@@ -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
-