changeset 1051:92f4bf2c5d73

HTTP GET in Lua
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 23 Jul 2014 12:59:28 +0200
parents 64f1842aae2e
children cc4ff680e2a0
files Core/Lua/LuaContext.cpp Core/Lua/LuaContext.h Core/Lua/LuaFunctionCall.cpp UnitTestsSources/LuaTests.cpp
diffstat 4 files changed, 173 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- 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");
--- 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 <EmbeddedResources.h>
-
 #include <boost/noncopyable.hpp>
 
 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();
 
--- 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)
--- 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 <boost/lexical_cast.hpp>
 
+#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<int>(Orthanc::Toolbox::StripSpaces(s)));
+
+  // Parse a JSON file
+  lua.Execute(s, "print(HttpGet(\"" + url + "\", true)['Name'])");
+  ASSERT_EQ("MyOrthanc", Orthanc::Toolbox::StripSpaces(s));
+#endif
+
+}