Skip to content

Commit

Permalink
MINIFICPP-1028 - http url parsing without port fails
Browse files Browse the repository at this point in the history
  • Loading branch information
arpadboda committed Sep 10, 2019
1 parent 9579284 commit 6516dad
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 44 deletions.
4 changes: 2 additions & 2 deletions libminifi/include/utils/HTTPClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -356,8 +356,8 @@ class BaseHTTPClient {

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 */
Expand Down
2 changes: 1 addition & 1 deletion libminifi/src/core/FlowConfiguration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
68 changes: 27 additions & 41 deletions libminifi/src/utils/HTTPClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
}
}

Expand Down
67 changes: 67 additions & 0 deletions libminifi/test/unit/HTTPUtilTests.cpp
Original file line number Diff line number Diff line change
@@ -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");
}

0 comments on commit 6516dad

Please sign in to comment.