Allow cancellation of HTTP requests
`NETWORK::HttpRequest()` now returns a HttpRequestFuture with a `Cancel()` method.
This commit is contained in:
@@ -2051,6 +2051,9 @@
|
||||
<Function name='GetHeld'/>
|
||||
<Function name='GetActive'/>
|
||||
</Class>
|
||||
<Class name='HttpRequestFuture'>
|
||||
<Function name='Cancel'/>
|
||||
</Class>
|
||||
<Class base='ActorFrame' name='TextBanner'>
|
||||
<Function name='Load'/>
|
||||
<Function name='SetFromSong'/>
|
||||
@@ -2498,6 +2501,7 @@
|
||||
<EnumValue name=''HttpErrorCode_TooManyRedirects'' value='13'/>
|
||||
<EnumValue name=''HttpErrorCode_ChunkReadError'' value='14'/>
|
||||
<EnumValue name=''HttpErrorCode_CannotReadBody'' value='15'/>
|
||||
<EnumValue name=''HttpErrorCode_Cancelled'' value='16'/>
|
||||
</Enum>
|
||||
<Enum name='ImageCacheMode'>
|
||||
<EnumValue name=''ImageCacheMode_Off'' value='0'/>
|
||||
|
||||
@@ -3560,7 +3560,7 @@ end
|
||||
<Function name='IsUrlAllowed' return='bool' arguments='string url'>
|
||||
Returns true if access to <code>url</code> is allowed.
|
||||
</Function>
|
||||
<Function name='HttpRequest' return='void' arguments='table params'>
|
||||
<Function name='HttpRequest' return='HttpRequestFuture' arguments='table params'>
|
||||
Performs an HTTP request.<br />
|
||||
Usage example:
|
||||
<pre><code>
|
||||
@@ -6210,6 +6210,12 @@ local spr = Def.Sprite{
|
||||
Returns true if the note was initiated.
|
||||
</Function>
|
||||
</Class>
|
||||
<Class name='HttpRequestFuture'>
|
||||
<Function name='Cancel' return='void' arguments=''>
|
||||
Cancels the running HTTP request. Does nothing if the request
|
||||
has already completed.
|
||||
</Function>
|
||||
</Class>
|
||||
<Class name='TextBanner' grouping='Actor'>
|
||||
<Function name='Load' return='void' arguments='string sMetricsGroup'>
|
||||
Loads the TextBanner from the specified metrics group.
|
||||
|
||||
+46
-5
@@ -10,6 +10,7 @@
|
||||
#include <ixwebsocket/IXUrlParser.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
@@ -94,7 +95,7 @@ bool NetworkManager::IsUrlAllowed(const std::string& url)
|
||||
return std::find(allowedHosts.begin(), allowedHosts.end(), host) != allowedHosts.end();
|
||||
}
|
||||
|
||||
void NetworkManager::HttpRequest(const HttpRequestArgs& args)
|
||||
HttpRequestFuturePtr NetworkManager::HttpRequest(const HttpRequestArgs& args)
|
||||
{
|
||||
ix::HttpRequestArgsPtr req = this->httpClient.createRequest(args.url, args.method);
|
||||
req->body = args.body;
|
||||
@@ -114,6 +115,8 @@ void NetworkManager::HttpRequest(const HttpRequestArgs& args)
|
||||
}
|
||||
|
||||
this->httpClient.performRequest(req, args.onResponse);
|
||||
|
||||
return std::make_shared<HttpRequestFuture>(req);
|
||||
}
|
||||
|
||||
std::string NetworkManager::UrlEncode(const std::string& value)
|
||||
@@ -126,10 +129,43 @@ std::string NetworkManager::EncodeQueryParameters(const std::unordered_map<std::
|
||||
return this->httpClient.serializeHttpParameters(query);
|
||||
}
|
||||
|
||||
int HttpRequestFuture::gc(lua_State *L)
|
||||
{
|
||||
void *udata = luaL_checkudata(L, 1, "HttpRequestFuture");
|
||||
auto futptr = static_cast<HttpRequestFuturePtr*>(udata);
|
||||
futptr->~shared_ptr();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int HttpRequestFuture::Cancel(lua_State *L)
|
||||
{
|
||||
void *udata = luaL_checkudata(L, 1, "HttpRequestFuture");
|
||||
auto fut = *static_cast<HttpRequestFuturePtr*>(udata);
|
||||
fut->args->cancel = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// lua start
|
||||
#include "LuaBinding.h"
|
||||
|
||||
static void registerHttpRequestMetatable(lua_State *L)
|
||||
{
|
||||
const luaL_Reg HttpRequest_meta[] = {
|
||||
{"__gc", HttpRequestFuture::gc},
|
||||
{"Cancel", HttpRequestFuture::Cancel},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
luaL_newmetatable(L, "HttpRequestFuture");
|
||||
luaL_register(L, NULL, HttpRequest_meta);
|
||||
lua_pushvalue(L, -1);
|
||||
lua_setfield(L, -2, "__index");
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
REGISTER_WITH_LUA_FUNCTION(registerHttpRequestMetatable)
|
||||
|
||||
/** @brief Allow Lua to have access to the NetworkManager. */
|
||||
class LunaNetworkManager: public Luna<NetworkManager>
|
||||
{
|
||||
@@ -302,7 +338,13 @@ public:
|
||||
|
||||
if (p->IsUrlAllowed(args.url))
|
||||
{
|
||||
p->HttpRequest(args);
|
||||
auto fut = p->HttpRequest(args);
|
||||
|
||||
void *vp = lua_newuserdata(L, sizeof(std::shared_ptr<HttpRequestFuture>));
|
||||
new(vp) std::shared_ptr<::HttpRequestFuture>(fut);
|
||||
luaL_getmetatable(L, "HttpRequestFuture");
|
||||
lua_setmetatable(L, -2);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -311,10 +353,8 @@ public:
|
||||
{
|
||||
handleUrlForbidden(L, args.url, onResponseRef);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int UrlEncode(T* p, lua_State *L)
|
||||
@@ -415,6 +455,7 @@ private:
|
||||
case ix::HttpErrorCode::TooManyRedirects: LuaHelpers::Push(L, HttpErrorCode_TooManyRedirects); break;
|
||||
case ix::HttpErrorCode::ChunkReadError: LuaHelpers::Push(L, HttpErrorCode_ChunkReadError); break;
|
||||
case ix::HttpErrorCode::CannotReadBody: LuaHelpers::Push(L, HttpErrorCode_CannotReadBody); break;
|
||||
case ix::HttpErrorCode::Cancelled: LuaHelpers::Push(L, HttpErrorCode_Cancelled); break;
|
||||
default: LuaHelpers::Push(L, HttpErrorCode_UnknownError); break;
|
||||
}
|
||||
lua_setfield(L, -2, "error");
|
||||
|
||||
+17
-1
@@ -5,6 +5,7 @@
|
||||
#include "StdString.h"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -36,6 +37,7 @@ enum HttpErrorCode
|
||||
HttpErrorCode_TooManyRedirects,
|
||||
HttpErrorCode_ChunkReadError,
|
||||
HttpErrorCode_CannotReadBody,
|
||||
HttpErrorCode_Cancelled,
|
||||
|
||||
NUM_HttpErrorCode,
|
||||
HttpErrorCode_Invalid,
|
||||
@@ -56,6 +58,20 @@ struct HttpRequestArgs
|
||||
std::function<void(const ix::HttpResponsePtr& response)> onResponse = [](const ix::HttpResponsePtr& response) {};
|
||||
};
|
||||
|
||||
class HttpRequestFuture
|
||||
{
|
||||
public:
|
||||
HttpRequestFuture(ix::HttpRequestArgsPtr& args) : args(args) {};
|
||||
|
||||
static int gc(lua_State *L);
|
||||
static int Cancel(lua_State *L);
|
||||
|
||||
private:
|
||||
ix::HttpRequestArgsPtr args;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<HttpRequestFuture> HttpRequestFuturePtr;
|
||||
|
||||
class NetworkManager
|
||||
{
|
||||
public:
|
||||
@@ -63,7 +79,7 @@ public:
|
||||
~NetworkManager();
|
||||
|
||||
bool IsUrlAllowed(const std::string& url);
|
||||
void HttpRequest(const HttpRequestArgs& args);
|
||||
HttpRequestFuturePtr HttpRequest(const HttpRequestArgs& args);
|
||||
std::string UrlEncode(const std::string& value);
|
||||
std::string EncodeQueryParameters(const std::unordered_map<std::string, std::string>& query);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user