Add HTTP API for Lua
Also fix a bug with Requests where any connection that took longer to finish than 15 seconds would be killed. Should have used CURLOPT_CONNECTTIMEOUT instead of CURLOPT_TIMEOUT when specifying the timeout, oops.
This commit is contained in:
parent
4d52531889
commit
fe87203eb4
@ -201,7 +201,7 @@ namespace http
|
|||||||
curl_easy_setopt(easy, CURLOPT_ERRORBUFFER, error_buffer);
|
curl_easy_setopt(easy, CURLOPT_ERRORBUFFER, error_buffer);
|
||||||
error_buffer[0] = 0;
|
error_buffer[0] = 0;
|
||||||
|
|
||||||
curl_easy_setopt(easy, CURLOPT_TIMEOUT, timeout);
|
curl_easy_setopt(easy, CURLOPT_CONNECTTIMEOUT, timeout);
|
||||||
curl_easy_setopt(easy, CURLOPT_HTTPHEADER, headers);
|
curl_easy_setopt(easy, CURLOPT_HTTPHEADER, headers);
|
||||||
curl_easy_setopt(easy, CURLOPT_URL, uri.c_str());
|
curl_easy_setopt(easy, CURLOPT_URL, uri.c_str());
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include "client/SaveFile.h"
|
#include "client/SaveFile.h"
|
||||||
#include "client/SaveInfo.h"
|
#include "client/SaveInfo.h"
|
||||||
#include "client/Client.h"
|
#include "client/Client.h"
|
||||||
|
#include "client/http/Request.h"
|
||||||
|
|
||||||
#include "graphics/Graphics.h"
|
#include "graphics/Graphics.h"
|
||||||
#include "graphics/Renderer.h"
|
#include "graphics/Renderer.h"
|
||||||
@ -152,6 +153,9 @@ LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m):
|
|||||||
initFileSystemAPI();
|
initFileSystemAPI();
|
||||||
initPlatformAPI();
|
initPlatformAPI();
|
||||||
initEventAPI();
|
initEventAPI();
|
||||||
|
#ifndef NOHTTP
|
||||||
|
initHttpAPI();
|
||||||
|
#endif
|
||||||
|
|
||||||
//Old TPT API
|
//Old TPT API
|
||||||
int currentElementMeta, currentElement;
|
int currentElementMeta, currentElement;
|
||||||
@ -3686,6 +3690,204 @@ int LuaScriptInterface::event_getmodifiers(lua_State * l)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RequestHandle
|
||||||
|
{
|
||||||
|
http::Request *request;
|
||||||
|
bool dead;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RequestHandle(ByteString &uri, std::map<ByteString, ByteString> &post_data, std::map<ByteString, ByteString> &headers)
|
||||||
|
{
|
||||||
|
dead = false;
|
||||||
|
request = new http::Request(uri);
|
||||||
|
for (auto &header : headers)
|
||||||
|
{
|
||||||
|
request->AddHeader(header.first, header.second);
|
||||||
|
}
|
||||||
|
request->AddPostData(post_data);
|
||||||
|
request->Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
~RequestHandle()
|
||||||
|
{
|
||||||
|
if (!Dead())
|
||||||
|
{
|
||||||
|
Cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Dead() const
|
||||||
|
{
|
||||||
|
return dead;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Done() const
|
||||||
|
{
|
||||||
|
return dead || request->CheckDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Running() const
|
||||||
|
{
|
||||||
|
return !dead && request->CheckStarted();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Progress(int *total, int *done)
|
||||||
|
{
|
||||||
|
if (!dead)
|
||||||
|
{
|
||||||
|
request->CheckProgress(total, done);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cancel()
|
||||||
|
{
|
||||||
|
if (!dead)
|
||||||
|
{
|
||||||
|
request->Cancel();
|
||||||
|
dead = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteString Finish(int *status_out)
|
||||||
|
{
|
||||||
|
ByteString data;
|
||||||
|
if (!dead)
|
||||||
|
{
|
||||||
|
if (request->CheckDone())
|
||||||
|
{
|
||||||
|
data = request->Finish(status_out);
|
||||||
|
dead = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static int http_request_gc(lua_State *l)
|
||||||
|
{
|
||||||
|
auto *rh = (RequestHandle *)luaL_checkudata(l, 1, "HTTPRequest");
|
||||||
|
rh->~RequestHandle();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int http_request_status(lua_State *l)
|
||||||
|
{
|
||||||
|
auto *rh = (RequestHandle *)luaL_checkudata(l, 1, "HTTPRequest");
|
||||||
|
if (rh->Dead())
|
||||||
|
{
|
||||||
|
lua_pushliteral(l, "dead");
|
||||||
|
}
|
||||||
|
else if (rh->Done())
|
||||||
|
{
|
||||||
|
lua_pushliteral(l, "done");
|
||||||
|
}
|
||||||
|
else if (rh->Running())
|
||||||
|
{
|
||||||
|
lua_pushliteral(l, "running");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lua_pushliteral(l, "queued");
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int http_request_progress(lua_State *l)
|
||||||
|
{
|
||||||
|
auto *rh = (RequestHandle *)luaL_checkudata(l, 1, "HTTPRequest");
|
||||||
|
if (!rh->Dead())
|
||||||
|
{
|
||||||
|
int total, done;
|
||||||
|
rh->Progress(&total, &done);
|
||||||
|
lua_pushinteger(l, total);
|
||||||
|
lua_pushinteger(l, done);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int http_request_cancel(lua_State *l)
|
||||||
|
{
|
||||||
|
auto *rh = (RequestHandle *)luaL_checkudata(l, 1, "HTTPRequest");
|
||||||
|
if (!rh->Dead())
|
||||||
|
{
|
||||||
|
rh->Cancel();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int http_request_finish(lua_State *l)
|
||||||
|
{
|
||||||
|
auto *rh = (RequestHandle *)luaL_checkudata(l, 1, "HTTPRequest");
|
||||||
|
if (!rh->Dead())
|
||||||
|
{
|
||||||
|
int status_out;
|
||||||
|
ByteString data = rh->Finish(&status_out);
|
||||||
|
lua_pushlstring(l, data.c_str(), data.size());
|
||||||
|
lua_pushinteger(l, status_out);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int http_request(lua_State *l)
|
||||||
|
{
|
||||||
|
ByteString uri(luaL_checkstring(l, 1));
|
||||||
|
std::map<ByteString, ByteString> post_data;
|
||||||
|
if (lua_istable(l, 2))
|
||||||
|
{
|
||||||
|
lua_pushnil(l);
|
||||||
|
while (lua_next(l, 2))
|
||||||
|
{
|
||||||
|
lua_pushvalue(l, -2);
|
||||||
|
post_data.emplace(lua_tostring(l, -1), lua_tostring(l, -2));
|
||||||
|
lua_pop(l, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::map<ByteString, ByteString> headers;
|
||||||
|
if (lua_istable(l, 3))
|
||||||
|
{
|
||||||
|
lua_pushnil(l);
|
||||||
|
while (lua_next(l, 3))
|
||||||
|
{
|
||||||
|
lua_pushvalue(l, -2);
|
||||||
|
headers.emplace(lua_tostring(l, -1), lua_tostring(l, -2));
|
||||||
|
lua_pop(l, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto *rh = (RequestHandle *)lua_newuserdata(l, sizeof(RequestHandle));
|
||||||
|
if (!rh)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
new(rh) RequestHandle(uri, post_data, headers);
|
||||||
|
luaL_newmetatable(l, "HTTPRequest");
|
||||||
|
lua_setmetatable(l, -2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LuaScriptInterface::initHttpAPI()
|
||||||
|
{
|
||||||
|
luaL_newmetatable(l, "HTTPRequest");
|
||||||
|
lua_pushcfunction(l, http_request_gc);
|
||||||
|
lua_setfield(l, -2, "__gc");
|
||||||
|
lua_newtable(l);
|
||||||
|
lua_pushcfunction(l, http_request_status);
|
||||||
|
lua_setfield(l, -2, "status");
|
||||||
|
lua_pushcfunction(l, http_request_progress);
|
||||||
|
lua_setfield(l, -2, "progress");
|
||||||
|
lua_pushcfunction(l, http_request_cancel);
|
||||||
|
lua_setfield(l, -2, "cancel");
|
||||||
|
lua_pushcfunction(l, http_request_finish);
|
||||||
|
lua_setfield(l, -2, "finish");
|
||||||
|
lua_setfield(l, -2, "__index");
|
||||||
|
struct luaL_Reg httpAPIMethods [] = {
|
||||||
|
{"request", http_request},
|
||||||
|
{NULL, NULL}
|
||||||
|
};
|
||||||
|
luaL_register(l, "http", httpAPIMethods);
|
||||||
|
}
|
||||||
|
|
||||||
bool LuaScriptInterface::HandleEvent(LuaEvents::EventTypes eventType, Event * event)
|
bool LuaScriptInterface::HandleEvent(LuaEvents::EventTypes eventType, Event * event)
|
||||||
{
|
{
|
||||||
return LuaEvents::HandleEvent(this, event, ByteString::Build("tptevents-", eventType));
|
return LuaEvents::HandleEvent(this, event, ByteString::Build("tptevents-", eventType));
|
||||||
@ -3792,7 +3994,6 @@ int strlcmp(const char* a, const char* b, int len)
|
|||||||
|
|
||||||
String highlight(String command)
|
String highlight(String command)
|
||||||
{
|
{
|
||||||
#define CMP(X) (String(wstart, len) == X)
|
|
||||||
StringBuilder result;
|
StringBuilder result;
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
String::value_type const*raw = command.c_str();
|
String::value_type const*raw = command.c_str();
|
||||||
@ -3806,12 +4007,14 @@ String highlight(String command)
|
|||||||
String::value_type const* wstart = raw+pos;
|
String::value_type const* wstart = raw+pos;
|
||||||
while((w = wstart[len]) && ((w >= 'A' && w <= 'Z') || (w >= 'a' && w <= 'z') || (w >= '0' && w <= '9') || w == '_'))
|
while((w = wstart[len]) && ((w >= 'A' && w <= 'Z') || (w >= 'a' && w <= 'z') || (w >= '0' && w <= '9') || w == '_'))
|
||||||
len++;
|
len++;
|
||||||
|
#define CMP(X) (String(wstart, len) == X)
|
||||||
if(CMP("and") || CMP("break") || CMP("do") || CMP("else") || CMP("elseif") || CMP("end") || CMP("for") || CMP("function") || CMP("if") || CMP("in") || CMP("local") || CMP("not") || CMP("or") || CMP("repeat") || CMP("return") || CMP("then") || CMP("until") || CMP("while"))
|
if(CMP("and") || CMP("break") || CMP("do") || CMP("else") || CMP("elseif") || CMP("end") || CMP("for") || CMP("function") || CMP("if") || CMP("in") || CMP("local") || CMP("not") || CMP("or") || CMP("repeat") || CMP("return") || CMP("then") || CMP("until") || CMP("while"))
|
||||||
result << "\x0F\xB5\x89\x01" << String(wstart, len) << "\bw";
|
result << "\x0F\xB5\x89\x01" << String(wstart, len) << "\bw";
|
||||||
else if(CMP("false") || CMP("nil") || CMP("true"))
|
else if(CMP("false") || CMP("nil") || CMP("true"))
|
||||||
result << "\x0F\xCB\x4B\x16" << String(wstart, len) << "\bw";
|
result << "\x0F\xCB\x4B\x16" << String(wstart, len) << "\bw";
|
||||||
else
|
else
|
||||||
result << "\x0F\x2A\xA1\x98" << String(wstart, len) << "\bw";
|
result << "\x0F\x2A\xA1\x98" << String(wstart, len) << "\bw";
|
||||||
|
#undef CMP
|
||||||
pos += len;
|
pos += len;
|
||||||
}
|
}
|
||||||
else if((c >= '0' && c <= '9') || (c == '.' && raw[pos + 1] >= '0' && raw[pos + 1] <= '9'))
|
else if((c >= '0' && c <= '9') || (c == '.' && raw[pos + 1] >= '0' && raw[pos + 1] <= '9'))
|
||||||
|
@ -180,6 +180,8 @@ class LuaScriptInterface: public CommandInterface
|
|||||||
static int event_unregister(lua_State * l);
|
static int event_unregister(lua_State * l);
|
||||||
static int event_getmodifiers(lua_State * l);
|
static int event_getmodifiers(lua_State * l);
|
||||||
|
|
||||||
|
void initHttpAPI();
|
||||||
|
|
||||||
std::vector<LuaSmartRef> lua_el_func_v, lua_gr_func_v, lua_cd_func_v;
|
std::vector<LuaSmartRef> lua_el_func_v, lua_gr_func_v, lua_cd_func_v;
|
||||||
std::vector<int> lua_el_mode_v;
|
std::vector<int> lua_el_mode_v;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user