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 2019/09/10 13:15:18 UTC

[nifi-minifi-cpp] branch master updated: MINIFICPP-1028 - http url parsing without port fails

This is an automated email from the ASF dual-hosted git repository.

phrocker pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git


The following commit(s) were added to refs/heads/master by this push:
     new d7d2a58  MINIFICPP-1028 - http url parsing without port fails
d7d2a58 is described below

commit d7d2a582ce627b9f2b2816210c1a7af46c28ebe7
Author: Arpad Boda <ab...@apache.org>
AuthorDate: Tue Sep 10 12:22:24 2019 +0200

    MINIFICPP-1028 - http url parsing without port fails
    
    This closes #645.
    
    Signed-off-by: Marc Parisi <ph...@apache.org>
---
 libminifi/include/utils/HTTPClient.h     |  4 +-
 libminifi/src/core/FlowConfiguration.cpp |  2 +-
 libminifi/src/utils/HTTPClient.cpp       | 68 +++++++++++++-------------------
 libminifi/test/unit/HTTPUtilTests.cpp    | 67 +++++++++++++++++++++++++++++++
 4 files changed, 97 insertions(+), 44 deletions(-)

diff --git a/libminifi/include/utils/HTTPClient.h b/libminifi/include/utils/HTTPClient.h
index d477f73..8cdc3ef 100644
--- a/libminifi/include/utils/HTTPClient.h
+++ b/libminifi/include/utils/HTTPClient.h
@@ -356,8 +356,8 @@ public:
 
 extern std::string get_token(utils::BaseHTTPClient *client, std::string username, std::string password);
 
-extern void parse_url(std::string *url, std::string *host, int *port, std::string *protocol);
-extern void parse_url(std::string *url, std::string *host, int *port, std::string *protocol, std::string *path, std::string *query);
+extern void parse_url(const std::string *url, std::string *host, int *port, std::string *protocol);
+extern void parse_url(const std::string *url, std::string *host, int *port, std::string *protocol, std::string *path, std::string *query);
 } /* namespace utils */
 } /* namespace minifi */
 } /* namespace nifi */
diff --git a/libminifi/src/core/FlowConfiguration.cpp b/libminifi/src/core/FlowConfiguration.cpp
index 1842c21..dafa6c5 100644
--- a/libminifi/src/core/FlowConfiguration.cpp
+++ b/libminifi/src/core/FlowConfiguration.cpp
@@ -71,7 +71,7 @@ std::unique_ptr<core::ProcessGroup> FlowConfiguration::updateFromPayload(const s
   auto payload = getRootFromPayload(yamlConfigPayload);
   if (!source.empty() && payload != nullptr) {
     std::string host, protocol, path, query, url = source;
-    int port;
+    int port = -1;
     utils::parse_url(&url, &host, &port, &protocol, &path, &query);
 
     std::string flow_id, bucket_id;
diff --git a/libminifi/src/utils/HTTPClient.cpp b/libminifi/src/utils/HTTPClient.cpp
index 35d8f6b..3328aa5 100644
--- a/libminifi/src/utils/HTTPClient.cpp
+++ b/libminifi/src/utils/HTTPClient.cpp
@@ -48,9 +48,9 @@ std::string get_token(utils::BaseHTTPClient *client, std::string username, std::
   return token;
 }
 
-void parse_url(std::string *url, std::string *host, int *port, std::string *protocol) {
-  std::string http("http://");
-  std::string https("https://");
+void parse_url(const std::string *url, std::string *host, int *port, std::string *protocol) {
+  static std::string http("http://");
+  static std::string https("https://");
 
   if (url->compare(0, http.size(), http) == 0)
     *protocol = http;
@@ -76,53 +76,39 @@ void parse_url(std::string *url, std::string *host, int *port, std::string *prot
       if (portStr.size() > 0) {
         *port = std::stoi(portStr);
       }
+    } else {
+      // In case the host contains no port, the first part is needed only
+      // For eg.: nifi.io/nifi
+      size_t ppos = host->find_first_of("/");
+      if (ppos != std::string::npos) {
+        *host = host->substr(0, ppos);
+      }
     }
   }
 }
 
-void parse_url(std::string *url, std::string *host, int *port, std::string *protocol, std::string *path, std::string *query) {
-  std::string http("http://");
-  std::string https("https://");
+void parse_url(const std::string *url, std::string *host, int *port, std::string *protocol, std::string *path, std::string *query) {
+  int temp_port = -1;
 
-  if (url->compare(0, http.size(), http) == 0)
-    *protocol = http;
-
-  if (url->compare(0, https.size(), https) == 0)
-    *protocol = https;
+  parse_url(url, host, &temp_port, protocol);
 
-  if (!protocol->empty()) {
-    size_t pos = url->find_first_of(":", protocol->size());
+  if (host->empty() || protocol->empty()) {
+    return;
+  }
 
-    if (pos == std::string::npos) {
-      pos = url->size();
-    }
-    size_t ppos = url->find_first_of("/", protocol->size());
-    if (pos == url->size() && ppos < url->size()) {
-      *host = url->substr(protocol->size(), ppos - protocol->size());
-    } else {
-      if (ppos < url->size())
-        *host = url->substr(protocol->size(), pos - protocol->size());
-      else
-        return;
-    }
-    if (pos < url->size() && (*url)[pos] == ':') {
-      if (ppos == std::string::npos) {
-        ppos = url->size();
-      }
-      std::string portStr(url->substr(pos + 1, ppos - pos - 1));
-      if (portStr.size() > 0) {
-        *port = std::stoi(portStr);
-      }
-    }
+  size_t base_len = host->size() + protocol->size();
+  if (temp_port != -1) {
+    *port = temp_port;
+    base_len += std::to_string(temp_port).size() + 1;  // +1 for the :
+  }
 
-    auto query_loc = url->find_first_of("?", ppos);
+  auto query_loc = url->find_first_of("?", base_len);
 
-    if (query_loc < url->size()) {
-      *path = url->substr(ppos + 1, query_loc - ppos - 1);
-      *query = url->substr(query_loc + 1, url->size() - query_loc - 1);
-    } else {
-      *path = url->substr(ppos + 1, url->size() - ppos - 1);
-    }
+  if (query_loc < url->size()) {
+    *path = url->substr(base_len + 1, query_loc - base_len - 1);
+    *query = url->substr(query_loc + 1, url->size() - query_loc - 1);
+  } else {
+    *path = url->substr(base_len + 1, url->size() - base_len - 1);
   }
 }
 
diff --git a/libminifi/test/unit/HTTPUtilTests.cpp b/libminifi/test/unit/HTTPUtilTests.cpp
new file mode 100644
index 0000000..e3b7c45
--- /dev/null
+++ b/libminifi/test/unit/HTTPUtilTests.cpp
@@ -0,0 +1,67 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+#include <iostream>
+#include "../TestBase.h"
+#include "utils/HTTPClient.h"
+
+TEST_CASE("TestHTTPUtils::simple", "[test parse no port]") {
+  std::string protocol, host;
+  int port = -1;
+  std::string url = "http://nifi.io/nifi";
+  minifi::utils::parse_url(&url, &host, &port, &protocol);
+  REQUIRE(port == -1);
+  REQUIRE(host == "nifi.io");
+  REQUIRE(protocol == "http://");
+}
+
+TEST_CASE("TestHTTPUtils::urlwithport", "[test parse with port]") {
+  std::string protocol, host;
+  int port = -1;
+  std::string url = "https://nifi.somewhere.far.away:321/nifi";
+  minifi::utils::parse_url(&url, &host, &port, &protocol);
+  REQUIRE(port == 321);
+  REQUIRE(host == "nifi.somewhere.far.away");
+  REQUIRE(protocol == "https://");
+}
+
+TEST_CASE("TestHTTPUtils::query", "[test parse query without port]") {
+  std::string protocol, host, path, query;
+  int port = -1;
+  std::string url = "https://nifi.io/nifi/path?what";
+  minifi::utils::parse_url(&url, &host, &port, &protocol, &path, &query);
+  REQUIRE(port == -1);
+  REQUIRE(host == "nifi.io");
+  REQUIRE(protocol == "https://");
+  REQUIRE(path == "nifi/path");
+  REQUIRE(query == "what");
+}
+
+TEST_CASE("TestHTTPUtils::querywithport", "[test parse query with port]") {
+  std::string protocol, host, path, query;
+  int port = -1;
+  std::string url = "http://nifi.io:4321/nifi_path?what_is_love";
+  minifi::utils::parse_url(&url, &host, &port, &protocol, &path, &query);
+  REQUIRE(port == 4321);
+  REQUIRE(host == "nifi.io");
+  REQUIRE(protocol == "http://");
+  REQUIRE(path == "nifi_path");
+  REQUIRE(query == "what_is_love");
+}
+