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='GetHeld'/>
|
||||||
<Function name='GetActive'/>
|
<Function name='GetActive'/>
|
||||||
</Class>
|
</Class>
|
||||||
|
<Class name='HttpRequestFuture'>
|
||||||
|
<Function name='Cancel'/>
|
||||||
|
</Class>
|
||||||
<Class base='ActorFrame' name='TextBanner'>
|
<Class base='ActorFrame' name='TextBanner'>
|
||||||
<Function name='Load'/>
|
<Function name='Load'/>
|
||||||
<Function name='SetFromSong'/>
|
<Function name='SetFromSong'/>
|
||||||
@@ -2498,6 +2501,7 @@
|
|||||||
<EnumValue name=''HttpErrorCode_TooManyRedirects'' value='13'/>
|
<EnumValue name=''HttpErrorCode_TooManyRedirects'' value='13'/>
|
||||||
<EnumValue name=''HttpErrorCode_ChunkReadError'' value='14'/>
|
<EnumValue name=''HttpErrorCode_ChunkReadError'' value='14'/>
|
||||||
<EnumValue name=''HttpErrorCode_CannotReadBody'' value='15'/>
|
<EnumValue name=''HttpErrorCode_CannotReadBody'' value='15'/>
|
||||||
|
<EnumValue name=''HttpErrorCode_Cancelled'' value='16'/>
|
||||||
</Enum>
|
</Enum>
|
||||||
<Enum name='ImageCacheMode'>
|
<Enum name='ImageCacheMode'>
|
||||||
<EnumValue name=''ImageCacheMode_Off'' value='0'/>
|
<EnumValue name=''ImageCacheMode_Off'' value='0'/>
|
||||||
|
|||||||
@@ -3560,7 +3560,7 @@ end
|
|||||||
<Function name='IsUrlAllowed' return='bool' arguments='string url'>
|
<Function name='IsUrlAllowed' return='bool' arguments='string url'>
|
||||||
Returns true if access to <code>url</code> is allowed.
|
Returns true if access to <code>url</code> is allowed.
|
||||||
</Function>
|
</Function>
|
||||||
<Function name='HttpRequest' return='void' arguments='table params'>
|
<Function name='HttpRequest' return='HttpRequestFuture' arguments='table params'>
|
||||||
Performs an HTTP request.<br />
|
Performs an HTTP request.<br />
|
||||||
Usage example:
|
Usage example:
|
||||||
<pre><code>
|
<pre><code>
|
||||||
@@ -6210,6 +6210,12 @@ local spr = Def.Sprite{
|
|||||||
Returns true if the note was initiated.
|
Returns true if the note was initiated.
|
||||||
</Function>
|
</Function>
|
||||||
</Class>
|
</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'>
|
<Class name='TextBanner' grouping='Actor'>
|
||||||
<Function name='Load' return='void' arguments='string sMetricsGroup'>
|
<Function name='Load' return='void' arguments='string sMetricsGroup'>
|
||||||
Loads the TextBanner from the specified metrics group.
|
Loads the TextBanner from the specified metrics group.
|
||||||
|
|||||||
+46
-5
@@ -10,6 +10,7 @@
|
|||||||
#include <ixwebsocket/IXUrlParser.h>
|
#include <ixwebsocket/IXUrlParser.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -94,7 +95,7 @@ bool NetworkManager::IsUrlAllowed(const std::string& url)
|
|||||||
return std::find(allowedHosts.begin(), allowedHosts.end(), host) != allowedHosts.end();
|
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);
|
ix::HttpRequestArgsPtr req = this->httpClient.createRequest(args.url, args.method);
|
||||||
req->body = args.body;
|
req->body = args.body;
|
||||||
@@ -114,6 +115,8 @@ void NetworkManager::HttpRequest(const HttpRequestArgs& args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
this->httpClient.performRequest(req, args.onResponse);
|
this->httpClient.performRequest(req, args.onResponse);
|
||||||
|
|
||||||
|
return std::make_shared<HttpRequestFuture>(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string NetworkManager::UrlEncode(const std::string& value)
|
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);
|
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
|
// lua start
|
||||||
#include "LuaBinding.h"
|
#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. */
|
/** @brief Allow Lua to have access to the NetworkManager. */
|
||||||
class LunaNetworkManager: public Luna<NetworkManager>
|
class LunaNetworkManager: public Luna<NetworkManager>
|
||||||
{
|
{
|
||||||
@@ -302,7 +338,13 @@ public:
|
|||||||
|
|
||||||
if (p->IsUrlAllowed(args.url))
|
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
|
else
|
||||||
{
|
{
|
||||||
@@ -311,10 +353,8 @@ public:
|
|||||||
{
|
{
|
||||||
handleUrlForbidden(L, args.url, onResponseRef);
|
handleUrlForbidden(L, args.url, onResponseRef);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
lua_pushnil(L);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int UrlEncode(T* p, lua_State *L)
|
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::TooManyRedirects: LuaHelpers::Push(L, HttpErrorCode_TooManyRedirects); break;
|
||||||
case ix::HttpErrorCode::ChunkReadError: LuaHelpers::Push(L, HttpErrorCode_ChunkReadError); break;
|
case ix::HttpErrorCode::ChunkReadError: LuaHelpers::Push(L, HttpErrorCode_ChunkReadError); break;
|
||||||
case ix::HttpErrorCode::CannotReadBody: LuaHelpers::Push(L, HttpErrorCode_CannotReadBody); 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;
|
default: LuaHelpers::Push(L, HttpErrorCode_UnknownError); break;
|
||||||
}
|
}
|
||||||
lua_setfield(L, -2, "error");
|
lua_setfield(L, -2, "error");
|
||||||
|
|||||||
+17
-1
@@ -5,6 +5,7 @@
|
|||||||
#include "StdString.h"
|
#include "StdString.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
@@ -36,6 +37,7 @@ enum HttpErrorCode
|
|||||||
HttpErrorCode_TooManyRedirects,
|
HttpErrorCode_TooManyRedirects,
|
||||||
HttpErrorCode_ChunkReadError,
|
HttpErrorCode_ChunkReadError,
|
||||||
HttpErrorCode_CannotReadBody,
|
HttpErrorCode_CannotReadBody,
|
||||||
|
HttpErrorCode_Cancelled,
|
||||||
|
|
||||||
NUM_HttpErrorCode,
|
NUM_HttpErrorCode,
|
||||||
HttpErrorCode_Invalid,
|
HttpErrorCode_Invalid,
|
||||||
@@ -56,6 +58,20 @@ struct HttpRequestArgs
|
|||||||
std::function<void(const ix::HttpResponsePtr& response)> onResponse = [](const ix::HttpResponsePtr& response) {};
|
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
|
class NetworkManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -63,7 +79,7 @@ public:
|
|||||||
~NetworkManager();
|
~NetworkManager();
|
||||||
|
|
||||||
bool IsUrlAllowed(const std::string& url);
|
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 UrlEncode(const std::string& value);
|
||||||
std::string EncodeQueryParameters(const std::unordered_map<std::string, std::string>& query);
|
std::string EncodeQueryParameters(const std::unordered_map<std::string, std::string>& query);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user