You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by ph...@apache.org on 2018/04/27 18:44:58 UTC

nifi-minifi-cpp git commit: MINIFICPP-463 Implemented urlEncode/urlDecode EL functions

Repository: nifi-minifi-cpp
Updated Branches:
  refs/heads/master de0c93806 -> 7958bd11b


MINIFICPP-463 Implemented urlEncode/urlDecode EL functions

This closes #305.

Signed-off-by: Marc Parisi <ph...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/commit/7958bd11
Tree: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/tree/7958bd11
Diff: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/diff/7958bd11

Branch: refs/heads/master
Commit: 7958bd11b40547dfc7275e22957cec01a1a7353d
Parents: de0c938
Author: Andrew I. Christianson <an...@andyic.org>
Authored: Fri Apr 20 13:06:22 2018 -0400
Committer: Marc Parisi <ph...@apache.org>
Committed: Fri Apr 27 14:43:54 2018 -0400

----------------------------------------------------------------------
 EXPRESSIONS.md                                  | 38 +++++++++++++-
 extensions/expression-language/CMakeLists.txt   |  3 ++
 extensions/expression-language/Expression.cpp   | 53 +++++++++++++++++++-
 .../ExpressionLanguageTests.cpp                 | 24 +++++++++
 4 files changed, 114 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7958bd11/EXPRESSIONS.md
----------------------------------------------------------------------
diff --git a/EXPRESSIONS.md b/EXPRESSIONS.md
index 4a72dae..51bba83 100644
--- a/EXPRESSIONS.md
+++ b/EXPRESSIONS.md
@@ -208,6 +208,8 @@ token, filename.
 - [`escapeCsv`](#escapecsv)
 - [`unescapeXml`](#unescapexml)
 - [`unescapeCsv`](#unescapecsv)
+- [`urlEncode`](#urlencode)
+- [`urlDecode`](#urldecode)
 
 ## Planned Features
 
@@ -229,8 +231,6 @@ token, filename.
 - `escapeHtml4`
 - `unescapeHtml3`
 - `unescapeHtml4`
-- `urlEncode`
-- `urlDecode`
 - `base64Encode`
 - `base64Decode`
 
@@ -1338,3 +1338,37 @@ to the rules of RFC 4180
 
 If the "message" attribute is `"Zero > One < ""two!"" & 'true'"`, then the
 Expression `${message:escapeCsv()}` will return `Zero > One < "two!" & 'true'`
+
+### urlEncode
+
+**Description**: Returns a URL-friendly version of the Subject. This is useful,
+for instance, when using an attribute value to indicate the URL of a website.
+
+**Subject Type**: String
+
+**Arguments**: No arguments
+
+**Return Type**: String
+
+**Examples**:
+
+We can URL-Encode an attribute named "url" by using the Expression
+`${url:urlEncode()}`. If the value of the "url" attribute is "some value with
+spaces", this Expression will then return "some%20value%20with%20spaces".
+
+### urlDecode
+
+**Description**: Converts a URL-friendly version of the Subject into a
+human-readable form.
+
+**Subject Type**: String
+
+**Arguments**: No arguments
+
+**Return Type**: String
+
+**Examples**:
+
+If we have a URL-Encoded attribute named "url" with the value
+"some%20value%20with%20spaces", then the Expression `${url:urlDecode()}` will
+return "some value with spaces".

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7958bd11/extensions/expression-language/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/extensions/expression-language/CMakeLists.txt b/extensions/expression-language/CMakeLists.txt
index b242d9a..d16b7d2 100644
--- a/extensions/expression-language/CMakeLists.txt
+++ b/extensions/expression-language/CMakeLists.txt
@@ -55,6 +55,9 @@ endif()
 
 find_package(UUID REQUIRED)
 target_link_libraries(minifi-expression-language-extensions ${LIBMINIFI} ${UUID_LIBRARIES})
+find_package(CURL REQUIRED)
+include_directories(${CURL_INCLUDE_DIRS})
+target_link_libraries(minifi-expression-language-extensions ${CURL_LIBRARIES})
 find_package(OpenSSL REQUIRED)
 include_directories(${OPENSSL_INCLUDE_DIR})
 target_link_libraries(minifi-expression-language-extensions ${CMAKE_DL_LIBS})

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7958bd11/extensions/expression-language/Expression.cpp
----------------------------------------------------------------------
diff --git a/extensions/expression-language/Expression.cpp b/extensions/expression-language/Expression.cpp
index c6f6d87..44a3981 100644
--- a/extensions/expression-language/Expression.cpp
+++ b/extensions/expression-language/Expression.cpp
@@ -28,6 +28,7 @@
 #include <utils/StringUtils.h>
 #include <expression/Expression.h>
 #include <regex>
+#include <curl/curl.h>
 #include "Driver.h"
 
 namespace org {
@@ -1109,6 +1110,50 @@ Value expr_unescapeCsv(const std::vector<Value> &args) {
   return Value(result);
 }
 
+Value expr_urlEncode(const std::vector<Value> &args) {
+  auto arg_0 = args[0].asString();
+  CURL *curl = curl_easy_init();
+  if (curl != nullptr) {
+    char *output = curl_easy_escape(curl,
+                                    arg_0.c_str(),
+                                    static_cast<int>(arg_0.length()));
+    if (output != nullptr) {
+      auto result = std::string(output);
+      curl_free(output);
+      curl_easy_cleanup(curl);
+      return Value(result);
+    } else {
+      curl_easy_cleanup(curl);
+      throw std::runtime_error("cURL failed to encode URL string");
+    }
+  } else {
+    throw std::runtime_error("Failed to initialize cURL");
+  }
+}
+
+Value expr_urlDecode(const std::vector<Value> &args) {
+  auto arg_0 = args[0].asString();
+  CURL *curl = curl_easy_init();
+  if (curl != nullptr) {
+    int out_len;
+    char *output = curl_easy_unescape(curl,
+                                      arg_0.c_str(),
+                                      static_cast<int>(arg_0.length()),
+                                      &out_len);
+    if (output != nullptr) {
+      auto result = std::string(output, static_cast<unsigned long>(out_len));
+      curl_free(output);
+      curl_easy_cleanup(curl);
+      return Value(result);
+    } else {
+      curl_easy_cleanup(curl);
+      throw std::runtime_error("cURL failed to decode URL string");
+    }
+  } else {
+    throw std::runtime_error("Failed to initialize cURL");
+  }
+}
+
 #ifdef EXPRESSION_LANGUAGE_USE_REGEX
 
 Value expr_replace(const std::vector<Value> &args) {
@@ -1242,8 +1287,8 @@ Value expr_toRadix(const std::vector<Value> &args) {
 
   const char chars[] =
       "0123456789ab"
-          "cdefghijklmn"
-          "opqrstuvwxyz";
+      "cdefghijklmn"
+      "opqrstuvwxyz";
   std::string str_num;
 
   while (value) {
@@ -1454,6 +1499,10 @@ Expression make_dynamic_function(const std::string &function_name,
     return make_dynamic_function_incomplete<expr_escapeCsv>(function_name, args, 0);
   } else if (function_name == "unescapeCsv") {
     return make_dynamic_function_incomplete<expr_unescapeCsv>(function_name, args, 0);
+  } else if (function_name == "urlEncode") {
+    return make_dynamic_function_incomplete<expr_urlEncode>(function_name, args, 0);
+  } else if (function_name == "urlDecode") {
+    return make_dynamic_function_incomplete<expr_urlDecode>(function_name, args, 0);
 #ifdef EXPRESSION_LANGUAGE_USE_REGEX
   } else if (function_name == "replace") {
     return make_dynamic_function_incomplete<expr_replace>(function_name, args, 2);

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/7958bd11/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
----------------------------------------------------------------------
diff --git a/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp b/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
index 421d263..40713c2 100644
--- a/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
+++ b/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
@@ -1144,3 +1144,27 @@ TEST_CASE("Encode Decode CSV", "[expressionEncodeDecodeCSV]") {  // NOLINT
   flow_file_a->addAttribute("message", "Zero > One < \"two!\" & 'true'");
   REQUIRE("Zero > One < \"two!\" & 'true'" == expr({flow_file_a}).asString());
 }
+
+TEST_CASE("Encode URL", "[expressionEncodeURL]") {  // NOLINT
+  auto expr = expression::compile("${message:urlEncode()}");
+
+  auto flow_file_a = std::make_shared<MockFlowFile>();
+  flow_file_a->addAttribute("message", "some value with spaces");
+  REQUIRE("some%20value%20with%20spaces" == expr({flow_file_a}).asString());
+}
+
+TEST_CASE("Decode URL", "[expressionDecodeURL]") {  // NOLINT
+  auto expr = expression::compile("${message:urlDecode()}");
+
+  auto flow_file_a = std::make_shared<MockFlowFile>();
+  flow_file_a->addAttribute("message", "some%20value%20with%20spaces");
+  REQUIRE("some value with spaces" == expr({flow_file_a}).asString());
+}
+
+TEST_CASE("Encode Decode URL", "[expressionEncodeDecodeURL]") {  // NOLINT
+  auto expr = expression::compile("${message:urlEncode():urlDecode()}");
+
+  auto flow_file_a = std::make_shared<MockFlowFile>();
+  flow_file_a->addAttribute("message", "some value with spaces");
+  REQUIRE("some value with spaces" == expr({flow_file_a}).asString());
+}