cUrlClient: Exported to Lua API.
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
// ManualBindings_Network.cpp
|
||||
|
||||
// Implements the cNetwork-related API bindings for Lua
|
||||
// Also implements the cUrlClient bindings
|
||||
|
||||
#include "Globals.h"
|
||||
#include "LuaTCPLink.h"
|
||||
@@ -12,6 +13,7 @@
|
||||
#include "LuaNameLookup.h"
|
||||
#include "LuaServerHandle.h"
|
||||
#include "LuaUDPEndpoint.h"
|
||||
#include "../HTTP/UrlClient.h"
|
||||
|
||||
|
||||
|
||||
@@ -903,6 +905,329 @@ static int tolua_cUDPEndpoint_Send(lua_State * L)
|
||||
|
||||
|
||||
|
||||
/** Used when the cUrlClient Lua request wants all the callbacks.
|
||||
Maps each callback onto a Lua function callback in the callback table. */
|
||||
class cFullUrlClientCallbacks:
|
||||
public cUrlClient::cCallbacks
|
||||
{
|
||||
public:
|
||||
/** Creates a new instance bound to the specified table of callbacks. */
|
||||
cFullUrlClientCallbacks(cLuaState::cTableRefPtr && a_Callbacks):
|
||||
m_Callbacks(std::move(a_Callbacks))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// cUrlClient::cCallbacks overrides:
|
||||
virtual void OnConnected(cTCPLink & a_Link) override
|
||||
{
|
||||
// TODO: Cannot push a cTCPLink to Lua, need to translate via cLuaTCPLink
|
||||
m_Callbacks->CallTableFnWithSelf("OnConnected", cLuaState::Nil, a_Link.GetRemoteIP(), a_Link.GetRemotePort());
|
||||
}
|
||||
|
||||
|
||||
virtual bool OnCertificateReceived() override
|
||||
{
|
||||
// TODO: The received cert needs proper type specification from the underlying cUrlClient framework and in the Lua engine as well
|
||||
bool res = true;
|
||||
m_Callbacks->CallTableFnWithSelf("OnCertificateReceived", cLuaState::Return, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
virtual void OnTlsHandshakeCompleted() override
|
||||
{
|
||||
m_Callbacks->CallTableFnWithSelf("OnTlsHandshakeCompleted");
|
||||
}
|
||||
|
||||
|
||||
virtual void OnRequestSent() override
|
||||
{
|
||||
m_Callbacks->CallTableFnWithSelf("OnRequestSent");
|
||||
}
|
||||
|
||||
|
||||
virtual void OnStatusLine(const AString & a_HttpVersion, int a_StatusCode, const AString & a_Rest) override
|
||||
{
|
||||
m_Callbacks->CallTableFnWithSelf("OnStatusLine", a_HttpVersion, a_StatusCode, a_Rest);
|
||||
}
|
||||
|
||||
|
||||
virtual void OnHeader(const AString & a_Key, const AString & a_Value) override
|
||||
{
|
||||
m_Callbacks->CallTableFnWithSelf("OnHeader", a_Key, a_Value);
|
||||
m_Headers[a_Key] = a_Value;
|
||||
}
|
||||
|
||||
|
||||
virtual void OnHeadersFinished() override
|
||||
{
|
||||
m_Callbacks->CallTableFnWithSelf("OnHeadersFinished", m_Headers);
|
||||
}
|
||||
|
||||
|
||||
virtual void OnBodyData(const void * a_Data, size_t a_Size) override
|
||||
{
|
||||
m_Callbacks->CallTableFnWithSelf("OnBodyData", AString(reinterpret_cast<const char *>(a_Data), a_Size));
|
||||
}
|
||||
|
||||
|
||||
virtual void OnBodyFinished() override
|
||||
{
|
||||
m_Callbacks->CallTableFnWithSelf("OnBodyFinished");
|
||||
}
|
||||
|
||||
|
||||
virtual void OnError(const AString & a_ErrorMsg) override
|
||||
{
|
||||
m_Callbacks->CallTableFnWithSelf("OnError", a_ErrorMsg);
|
||||
}
|
||||
|
||||
|
||||
virtual void OnRedirecting(const AString & a_NewLocation) override
|
||||
{
|
||||
m_Callbacks->CallTableFnWithSelf("OnRedirecting", a_NewLocation);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
/** The Lua table containing the callbacks. */
|
||||
cLuaState::cTableRefPtr m_Callbacks;
|
||||
|
||||
/** Accumulator for all the headers to be reported in the OnHeadersFinished() callback. */
|
||||
AStringMap m_Headers;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Used when the cUrlClient Lua request has just a single callback.
|
||||
The callback is used to report the entire body at once, together with the HTTP headers, or to report an error:
|
||||
callback("BodyContents", {headers})
|
||||
callback(nil, "ErrorMessage")
|
||||
Accumulates the body contents into a single string until the body is finished.
|
||||
Accumulates all HTTP headers into an AStringMap. */
|
||||
class cSimpleUrlClientCallbacks:
|
||||
public cUrlClient::cCallbacks
|
||||
{
|
||||
public:
|
||||
/** Creates a new instance that uses the specified callback to report when request finishes. */
|
||||
cSimpleUrlClientCallbacks(cLuaState::cCallbackPtr && a_Callback):
|
||||
m_Callback(std::move(a_Callback))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
virtual void OnHeader(const AString & a_Key, const AString & a_Value) override
|
||||
{
|
||||
m_Headers[a_Key] = a_Value;
|
||||
}
|
||||
|
||||
|
||||
virtual void OnBodyData(const void * a_Data, size_t a_Size) override
|
||||
{
|
||||
m_ResponseBody.append(reinterpret_cast<const char *>(a_Data), a_Size);
|
||||
}
|
||||
|
||||
|
||||
virtual void OnBodyFinished() override
|
||||
{
|
||||
m_Callback->Call(m_ResponseBody, m_Headers);
|
||||
}
|
||||
|
||||
|
||||
virtual void OnError(const AString & a_ErrorMsg) override
|
||||
{
|
||||
m_Callback->Call(cLuaState::Nil, a_ErrorMsg);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/** The callback to call when the request finishes. */
|
||||
cLuaState::cCallbackPtr m_Callback;
|
||||
|
||||
/** The accumulator for the partial body data, so that OnBodyFinished() can send the entire thing at once. */
|
||||
AString m_ResponseBody;
|
||||
|
||||
/** Accumulator for all the headers to be reported in the combined callback. */
|
||||
AStringMap m_Headers;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Common code shared among the cUrlClient request methods.
|
||||
a_Method is the method name to be used in the request.
|
||||
a_UrlStackIdx is the position on the Lua stack of the Url parameter. */
|
||||
static int tolua_cUrlClient_Request_Common(lua_State * a_LuaState, const AString & a_Method, int a_UrlStackIdx)
|
||||
{
|
||||
// Check params:
|
||||
cLuaState L(a_LuaState);
|
||||
if (!L.CheckParamString(a_UrlStackIdx))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read params:
|
||||
AString url, requestBody;
|
||||
AStringMap headers, options;
|
||||
cLuaState::cTableRefPtr callbacks;
|
||||
cLuaState::cCallbackPtr onCompleteBodyCallback;
|
||||
if (!L.GetStackValues(a_UrlStackIdx, url))
|
||||
{
|
||||
L.LogApiCallParamFailure("cUrlClient:Request()", Printf("URL (%d)", a_UrlStackIdx).c_str());
|
||||
L.Push(false);
|
||||
L.Push("Invalid params");
|
||||
return 2;
|
||||
}
|
||||
cUrlClient::cCallbacksPtr urlClientCallbacks;
|
||||
if (lua_istable(L, a_UrlStackIdx + 1))
|
||||
{
|
||||
if (!L.GetStackValue(a_UrlStackIdx + 1, callbacks))
|
||||
{
|
||||
L.LogApiCallParamFailure("cUrlClient:Request()", Printf("CallbacksTable (%d)", a_UrlStackIdx + 1).c_str());
|
||||
L.Push(false);
|
||||
L.Push("Invalid Callbacks param");
|
||||
return 2;
|
||||
}
|
||||
urlClientCallbacks = cpp14::make_unique<cFullUrlClientCallbacks>(std::move(callbacks));
|
||||
}
|
||||
else if (lua_isfunction(L, a_UrlStackIdx + 1))
|
||||
{
|
||||
if (!L.GetStackValue(a_UrlStackIdx + 1, onCompleteBodyCallback))
|
||||
{
|
||||
L.LogApiCallParamFailure("cUrlClient:Request()", Printf("CallbacksFn (%d)", a_UrlStackIdx + 1).c_str());
|
||||
L.Push(false);
|
||||
L.Push("Invalid OnCompleteBodyCallback param");
|
||||
return 2;
|
||||
}
|
||||
urlClientCallbacks = cpp14::make_unique<cSimpleUrlClientCallbacks>(std::move(onCompleteBodyCallback));
|
||||
}
|
||||
else
|
||||
{
|
||||
L.LogApiCallParamFailure("cUrlClient:Request()", Printf("Callbacks (%d)", a_UrlStackIdx + 1).c_str());
|
||||
L.Push(false);
|
||||
L.Push("Invalid OnCompleteBodyCallback param");
|
||||
return 2;
|
||||
}
|
||||
if (!L.GetStackValues(a_UrlStackIdx + 2, cLuaState::cOptionalParam<AStringMap>(headers), cLuaState::cOptionalParam<AString>(requestBody), cLuaState::cOptionalParam<AStringMap>(options)))
|
||||
{
|
||||
L.LogApiCallParamFailure("cUrlClient:Request()", Printf("Header, Body or Options (%d, %d, %d)", a_UrlStackIdx + 2, a_UrlStackIdx + 3, a_UrlStackIdx + 4).c_str());
|
||||
L.Push(false);
|
||||
L.Push("Invalid params");
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Make the request:
|
||||
auto res = cUrlClient::Request(a_Method, url, std::move(urlClientCallbacks), std::move(headers), std::move(requestBody), std::move(options));
|
||||
if (!res.first)
|
||||
{
|
||||
L.Push(false);
|
||||
L.Push(res.second);
|
||||
return 2;
|
||||
}
|
||||
L.Push(true);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Implements cUrlClient:Get() using cUrlClient::Request(). */
|
||||
static int tolua_cUrlClient_Delete(lua_State * a_LuaState)
|
||||
{
|
||||
/* Function signatures:
|
||||
cUrlClient:Delete(URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
|
||||
cUrlClient:Delete(URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
|
||||
*/
|
||||
|
||||
return tolua_cUrlClient_Request_Common(a_LuaState, "DELETE", 2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Implements cUrlClient:Get() using cUrlClient::Request(). */
|
||||
static int tolua_cUrlClient_Get(lua_State * a_LuaState)
|
||||
{
|
||||
/* Function signatures:
|
||||
cUrlClient:Get(URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
|
||||
cUrlClient:Get(URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
|
||||
*/
|
||||
|
||||
return tolua_cUrlClient_Request_Common(a_LuaState, "GET", 2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Implements cUrlClient:Post() using cUrlClient::Request(). */
|
||||
static int tolua_cUrlClient_Post(lua_State * a_LuaState)
|
||||
{
|
||||
/* Function signatures:
|
||||
cUrlClient:Post(URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
|
||||
cUrlClient:Post(URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
|
||||
*/
|
||||
|
||||
return tolua_cUrlClient_Request_Common(a_LuaState, "POST", 2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Implements cUrlClient:Put() using cUrlClient::Request(). */
|
||||
static int tolua_cUrlClient_Put(lua_State * a_LuaState)
|
||||
{
|
||||
/* Function signatures:
|
||||
cUrlClient:Put(URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
|
||||
cUrlClient:Put(URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
|
||||
*/
|
||||
|
||||
return tolua_cUrlClient_Request_Common(a_LuaState, "PUT", 2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Binds cUrlClient::Request(). */
|
||||
static int tolua_cUrlClient_Request(lua_State * a_LuaState)
|
||||
{
|
||||
/* Function signatures:
|
||||
cUrlClient:Request(Method, URL, {CallbacksFnTable}, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
|
||||
cUrlClient:Request(Method, URL, OnCompleteBodyCallback, [{HeadersMapTable}], [RequestBody], [{OptionsMapTable}]) -> true / false + string
|
||||
*/
|
||||
|
||||
// Check that the Method param is a string:
|
||||
cLuaState L(a_LuaState);
|
||||
if (!L.CheckParamString(2))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Redirect the rest to the common code:
|
||||
AString method;
|
||||
if (!L.GetStackValue(2, method))
|
||||
{
|
||||
L.LogApiCallParamFailure("cUrlClient:Request", "Method (2)");
|
||||
L.Push(cLuaState::Nil);
|
||||
L.Push("Invalid params");
|
||||
return 2;
|
||||
}
|
||||
return tolua_cUrlClient_Request_Common(a_LuaState, method, 3);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Register the bindings:
|
||||
|
||||
@@ -913,10 +1238,12 @@ void cManualBindings::BindNetwork(lua_State * tolua_S)
|
||||
tolua_usertype(tolua_S, "cServerHandle");
|
||||
tolua_usertype(tolua_S, "cTCPLink");
|
||||
tolua_usertype(tolua_S, "cUDPEndpoint");
|
||||
tolua_usertype(tolua_S, "cUrlClient");
|
||||
tolua_cclass(tolua_S, "cNetwork", "cNetwork", "", nullptr);
|
||||
tolua_cclass(tolua_S, "cServerHandle", "cServerHandle", "", tolua_collect_cServerHandle);
|
||||
tolua_cclass(tolua_S, "cTCPLink", "cTCPLink", "", nullptr);
|
||||
tolua_cclass(tolua_S, "cUDPEndpoint", "cUDPEndpoint", "", tolua_collect_cUDPEndpoint);
|
||||
tolua_cclass(tolua_S, "cUrlClient", "cUrlClient", "", nullptr);
|
||||
|
||||
// Fill in the functions (alpha-sorted):
|
||||
tolua_beginmodule(tolua_S, "cNetwork");
|
||||
@@ -953,6 +1280,13 @@ void cManualBindings::BindNetwork(lua_State * tolua_S)
|
||||
tolua_function(tolua_S, "Send", tolua_cUDPEndpoint_Send);
|
||||
tolua_endmodule(tolua_S);
|
||||
|
||||
tolua_beginmodule(tolua_S, "cUrlClient");
|
||||
tolua_function(tolua_S, "Delete", tolua_cUrlClient_Delete);
|
||||
tolua_function(tolua_S, "Get", tolua_cUrlClient_Get);
|
||||
tolua_function(tolua_S, "Post", tolua_cUrlClient_Post);
|
||||
tolua_function(tolua_S, "Put", tolua_cUrlClient_Put);
|
||||
tolua_function(tolua_S, "Request", tolua_cUrlClient_Request);
|
||||
tolua_endmodule(tolua_S);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user