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());
+}