# HG changeset patch # User Sebastien Jodogne # Date 1406113168 -7200 # Node ID 92f4bf2c5d73d306aee3ebd27cff96f8cb92aeaa # Parent 64f1842aae2e9c00248cff54dbfeb89ec86ada17 HTTP GET in Lua diff -r 64f1842aae2e -r 92f4bf2c5d73 Core/Lua/LuaContext.cpp --- a/Core/Lua/LuaContext.cpp Wed Jul 23 11:36:35 2014 +0200 +++ b/Core/Lua/LuaContext.cpp Wed Jul 23 12:59:28 2014 +0200 @@ -44,7 +44,7 @@ namespace Orthanc { - int LuaContext::PrintToLog(lua_State *state) + LuaContext& LuaContext::GetLuaContext(lua_State *state) { // Get the pointer to the "LuaContext" underlying object lua_getglobal(state, "_LuaContext"); @@ -53,6 +53,13 @@ assert(that != NULL); lua_pop(state, 1); + return *that; + } + + int LuaContext::PrintToLog(lua_State *state) + { + LuaContext& that = GetLuaContext(state); + // http://medek.wordpress.com/2009/02/03/wrapping-lua-errors-and-print-function/ int nArgs = lua_gettop(state); lua_getglobal(state, "tostring"); @@ -80,12 +87,140 @@ } LOG(WARNING) << "Lua says: " << result; - that->log_.append(result); - that->log_.append("\n"); + that.log_.append(result); + that.log_.append("\n"); return 0; } + + int LuaContext::CallHttpGet(lua_State *state) + { + LuaContext& that = GetLuaContext(state); + + // Check that there is 1 string argument + int nArgs = lua_gettop(state); + if ((nArgs != 1 && nArgs != 2) || + !lua_isstring(state, 1) || + (nArgs == 2 && !lua_isboolean(state, 2))) + { + LOG(ERROR) << "Lua: Bad URL in HttpGet"; + + lua_pushstring(state, "ERROR"); + return 1; + } + + // Configure the HTTP client class + const char* url = lua_tostring(state, 1); + bool isJson = (nArgs == 2 && lua_toboolean(state, 2)); + that.httpClient_.SetMethod(HttpMethod_Get); + that.httpClient_.SetUrl(url); + + // Do the HTTP GET request + std::string str; + Json::Value json; + + try + { + if (isJson) + { + that.httpClient_.Apply(json); + } + else + { + that.httpClient_.Apply(str); + } + } + catch (OrthancException& e) + { + LOG(ERROR) << "Lua: Error in HttpGet for URL " << url << ": " << e.What(); + + lua_pushstring(state, "ERROR"); + return 1; + } + + // Return the result of the HTTP GET + if (isJson) + { + that.PushJson(json); + } + else + { + lua_pushstring(state, str.c_str()); + } + + return 1; + } + + + void LuaContext::PushJson(const Json::Value& value) + { + if (value.isString()) + { + lua_pushstring(lua_, value.asCString()); + } + else if (value.isDouble()) + { + lua_pushnumber(lua_, value.asDouble()); + } + else if (value.isInt()) + { + lua_pushinteger(lua_, value.asInt()); + } + else if (value.isUInt()) + { + lua_pushinteger(lua_, value.asUInt()); + } + else if (value.isBool()) + { + lua_pushboolean(lua_, value.asBool()); + } + else if (value.isNull()) + { + lua_pushnil(lua_); + } + else if (value.isArray()) + { + lua_newtable(lua_); + + // http://lua-users.org/wiki/SimpleLuaApiExample + for (Json::Value::ArrayIndex i = 0; i < value.size(); i++) + { + // Push the table index (note the "+1" because of Lua conventions) + lua_pushnumber(lua_, i + 1); + + // Push the value of the cell + PushJson(value[i]); + + // Stores the pair in the table + lua_rawset(lua_, -3); + } + } + else if (value.isObject()) + { + lua_newtable(lua_); + + Json::Value::Members members = value.getMemberNames(); + + for (Json::Value::Members::const_iterator + it = members.begin(); it != members.end(); ++it) + { + // Push the index of the cell + lua_pushstring(lua_, it->c_str()); + + // Push the value of the cell + PushJson(value[*it]); + + // Stores the pair in the table + lua_rawset(lua_, -3); + } + } + else + { + throw LuaException("Unsupported JSON conversion"); + } + } + LuaContext::LuaContext() { @@ -97,6 +232,7 @@ luaL_openlibs(lua_); lua_register(lua_, "print", PrintToLog); + lua_register(lua_, "HttpGet", CallHttpGet); lua_pushlightuserdata(lua_, this); lua_setglobal(lua_, "_LuaContext"); diff -r 64f1842aae2e -r 92f4bf2c5d73 Core/Lua/LuaContext.h --- a/Core/Lua/LuaContext.h Wed Jul 23 11:36:35 2014 +0200 +++ b/Core/Lua/LuaContext.h Wed Jul 23 12:59:28 2014 +0200 @@ -33,6 +33,7 @@ #pragma once #include "LuaException.h" +#include "../HttpClient.h" extern "C" { @@ -40,7 +41,6 @@ } #include - #include namespace Orthanc @@ -52,12 +52,19 @@ lua_State *lua_; std::string log_; + HttpClient httpClient_; + + static LuaContext& GetLuaContext(lua_State *state); static int PrintToLog(lua_State *L); + static int CallHttpGet(lua_State *L); + void Execute(std::string* output, const std::string& command); + void PushJson(const Json::Value& value); + public: LuaContext(); diff -r 64f1842aae2e -r 92f4bf2c5d73 Core/Lua/LuaFunctionCall.cpp --- a/Core/Lua/LuaFunctionCall.cpp Wed Jul 23 11:36:35 2014 +0200 +++ b/Core/Lua/LuaFunctionCall.cpp Wed Jul 23 12:59:28 2014 +0200 @@ -85,71 +85,7 @@ void LuaFunctionCall::PushJson(const Json::Value& value) { CheckAlreadyExecuted(); - - if (value.isString()) - { - lua_pushstring(context_.lua_, value.asCString()); - } - else if (value.isDouble()) - { - lua_pushnumber(context_.lua_, value.asDouble()); - } - else if (value.isInt()) - { - lua_pushinteger(context_.lua_, value.asInt()); - } - else if (value.isUInt()) - { - lua_pushinteger(context_.lua_, value.asUInt()); - } - else if (value.isBool()) - { - lua_pushboolean(context_.lua_, value.asBool()); - } - else if (value.isNull()) - { - lua_pushnil(context_.lua_); - } - else if (value.isArray()) - { - lua_newtable(context_.lua_); - - // http://lua-users.org/wiki/SimpleLuaApiExample - for (Json::Value::ArrayIndex i = 0; i < value.size(); i++) - { - // Push the table index (note the "+1" because of Lua conventions) - lua_pushnumber(context_.lua_, i + 1); - - // Push the value of the cell - PushJson(value[i]); - - // Stores the pair in the table - lua_rawset(context_.lua_, -3); - } - } - else if (value.isObject()) - { - lua_newtable(context_.lua_); - - Json::Value::Members members = value.getMemberNames(); - - for (Json::Value::Members::const_iterator - it = members.begin(); it != members.end(); ++it) - { - // Push the index of the cell - lua_pushstring(context_.lua_, it->c_str()); - - // Push the value of the cell - PushJson(value[*it]); - - // Stores the pair in the table - lua_rawset(context_.lua_, -3); - } - } - else - { - throw LuaException("Unsupported JSON conversion"); - } + context_.PushJson(value); } void LuaFunctionCall::ExecuteInternal(int numOutputs) diff -r 64f1842aae2e -r 92f4bf2c5d73 UnitTestsSources/LuaTests.cpp --- a/UnitTestsSources/LuaTests.cpp Wed Jul 23 11:36:35 2014 +0200 +++ b/UnitTestsSources/LuaTests.cpp Wed Jul 23 12:59:28 2014 +0200 @@ -33,10 +33,15 @@ #include "PrecompiledHeadersUnitTests.h" #include "gtest/gtest.h" +#include "../Core/Toolbox.h" #include "../Core/Lua/LuaFunctionCall.h" #include +#if !defined(UNIT_TESTS_WITH_HTTP_CONNEXIONS) +#error "Please set UNIT_TESTS_WITH_HTTP_CONNEXIONS" +#endif + TEST(Lua, Json) { @@ -232,3 +237,23 @@ ASSERT_EQ("test2", v["List"][1][2].asString()); } } + +TEST(Lua, Http) +{ + const std::string url("http://orthanc.googlecode.com/hg/Resources/Configuration.json"); + + Orthanc::LuaContext lua; + std::string s; + lua.Execute(s, "print(HttpGet({}))"); + ASSERT_EQ("ERROR", Orthanc::Toolbox::StripSpaces(s)); + +#if UNIT_TESTS_WITH_HTTP_CONNEXIONS == 1 + lua.Execute(s, "print(string.len(HttpGet(\"" + url + "\")))"); + ASSERT_LE(1000, boost::lexical_cast(Orthanc::Toolbox::StripSpaces(s))); + + // Parse a JSON file + lua.Execute(s, "print(HttpGet(\"" + url + "\", true)['Name'])"); + ASSERT_EQ("MyOrthanc", Orthanc::Toolbox::StripSpaces(s)); +#endif + +}