mirror of https://github.com/Icinga/icinga2.git
Merge pull request #6857 from Icinga/bugfix/check_nscp_api-query-sorted-6536
Url#m_Query: preserve order
This commit is contained in:
commit
b08d485a41
|
@ -42,11 +42,11 @@ void ApiClient::ExecuteScript(const String& session, const String& command, bool
|
|||
url->SetPort(m_Connection->GetPort());
|
||||
url->SetPath({ "v1", "console", "execute-script" });
|
||||
|
||||
std::map<String, std::vector<String> > params;
|
||||
params["session"].push_back(session);
|
||||
params["command"].push_back(command);
|
||||
params["sandboxed"].emplace_back(sandboxed ? "1" : "0");
|
||||
url->SetQuery(params);
|
||||
url->SetQuery({
|
||||
{"session", session},
|
||||
{"command", command},
|
||||
{"sandboxed", sandboxed ? "1" : "0"}
|
||||
});
|
||||
|
||||
try {
|
||||
std::shared_ptr<HttpRequest> req = m_Connection->NewRequest();
|
||||
|
@ -121,11 +121,11 @@ void ApiClient::AutocompleteScript(const String& session, const String& command,
|
|||
url->SetPort(m_Connection->GetPort());
|
||||
url->SetPath({ "v1", "console", "auto-complete-script" });
|
||||
|
||||
std::map<String, std::vector<String> > params;
|
||||
params["session"].push_back(session);
|
||||
params["command"].push_back(command);
|
||||
params["sandboxed"].emplace_back(sandboxed ? "1" : "0");
|
||||
url->SetQuery(params);
|
||||
url->SetQuery({
|
||||
{"session", session},
|
||||
{"command", command},
|
||||
{"sandboxed", sandboxed ? "1" : "0"}
|
||||
});
|
||||
|
||||
try {
|
||||
std::shared_ptr<HttpRequest> req = m_Connection->NewRequest();
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "remote/httputility.hpp"
|
||||
#include "base/json.hpp"
|
||||
#include "base/logger.hpp"
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
using namespace icinga;
|
||||
|
||||
|
@ -44,8 +46,12 @@ Dictionary::Ptr HttpUtility::FetchRequestParameters(HttpRequest& request)
|
|||
if (!result)
|
||||
result = new Dictionary();
|
||||
|
||||
typedef std::pair<String, std::vector<String> > kv_pair;
|
||||
for (const kv_pair& kv : request.RequestUrl->GetQuery()) {
|
||||
std::map<String, std::vector<String>> query;
|
||||
for (const auto& kv : request.RequestUrl->GetQuery()) {
|
||||
query[kv.first].emplace_back(kv.second);
|
||||
}
|
||||
|
||||
for (auto& kv : query) {
|
||||
result->Set(kv.first, Array::FromVector(kv.second));
|
||||
}
|
||||
|
||||
|
|
|
@ -138,33 +138,11 @@ const std::vector<String>& Url::GetPath() const
|
|||
return m_Path;
|
||||
}
|
||||
|
||||
const std::map<String, std::vector<String> >& Url::GetQuery() const
|
||||
const std::vector<std::pair<String, String>>& Url::GetQuery() const
|
||||
{
|
||||
return m_Query;
|
||||
}
|
||||
|
||||
String Url::GetQueryElement(const String& name) const
|
||||
{
|
||||
auto it = m_Query.find(name);
|
||||
|
||||
if (it == m_Query.end())
|
||||
return String();
|
||||
|
||||
return it->second.back();
|
||||
}
|
||||
|
||||
const std::vector<String>& Url::GetQueryElements(const String& name) const
|
||||
{
|
||||
auto it = m_Query.find(name);
|
||||
|
||||
if (it == m_Query.end()) {
|
||||
static std::vector<String> emptyVector;
|
||||
return emptyVector;
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
String Url::GetFragment() const
|
||||
{
|
||||
return m_Fragment;
|
||||
|
@ -200,7 +178,7 @@ void Url::SetPath(const std::vector<String>& path)
|
|||
m_Path = path;
|
||||
}
|
||||
|
||||
void Url::SetQuery(const std::map<String, std::vector<String> >& query)
|
||||
void Url::SetQuery(const std::vector<std::pair<String, String>>& query)
|
||||
{
|
||||
m_Query = query;
|
||||
}
|
||||
|
@ -212,16 +190,7 @@ void Url::SetArrayFormatUseBrackets(bool useBrackets)
|
|||
|
||||
void Url::AddQueryElement(const String& name, const String& value)
|
||||
{
|
||||
auto it = m_Query.find(name);
|
||||
if (it == m_Query.end()) {
|
||||
m_Query[name] = std::vector<String> { value };
|
||||
} else
|
||||
m_Query[name].push_back(value);
|
||||
}
|
||||
|
||||
void Url::SetQueryElements(const String& name, const std::vector<String>& values)
|
||||
{
|
||||
m_Query[name] = values;
|
||||
m_Query.emplace_back(name, value);
|
||||
}
|
||||
|
||||
void Url::SetFragment(const String& fragment) {
|
||||
|
@ -255,38 +224,16 @@ String Url::Format(bool onlyPathAndQuery, bool printCredentials) const
|
|||
if (!m_Query.empty()) {
|
||||
typedef std::pair<String, std::vector<String> > kv_pair;
|
||||
|
||||
for (const kv_pair& kv : m_Query) {
|
||||
for (const auto& kv : m_Query) {
|
||||
String key = Utility::EscapeString(kv.first, ACQUERY_ENCODE, false);
|
||||
if (param.IsEmpty())
|
||||
param = "?";
|
||||
else
|
||||
param += "&";
|
||||
|
||||
// Just one (or one empty) value
|
||||
if (kv.second.size() == 1) {
|
||||
param += key;
|
||||
param += kv.second[0].IsEmpty() ?
|
||||
String() : "=" + Utility::EscapeString(kv.second[0], ACQUERY_ENCODE, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Array
|
||||
String temp;
|
||||
for (const String& s : kv.second) {
|
||||
if (!temp.IsEmpty())
|
||||
temp += "&";
|
||||
|
||||
temp += key;
|
||||
|
||||
if (m_ArrayFormatUseBrackets) {
|
||||
if (kv.second.size() > 1)
|
||||
temp += "[]";
|
||||
}
|
||||
|
||||
if (!s.IsEmpty())
|
||||
temp += "=" + Utility::EscapeString(s, ACQUERY_ENCODE, false);
|
||||
}
|
||||
param += temp;
|
||||
param += key;
|
||||
param += kv.second.IsEmpty() ?
|
||||
String() : "=" + Utility::EscapeString(kv.second, ACQUERY_ENCODE, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,14 +355,7 @@ bool Url::ParseQuery(const String& query)
|
|||
if (!ValidateToken(key, ACQUERY))
|
||||
return false;
|
||||
|
||||
key = Utility::UnescapeString(key);
|
||||
|
||||
auto it = m_Query.find(key);
|
||||
|
||||
if (it == m_Query.end()) {
|
||||
m_Query[key] = std::vector<String> { std::move(value) };
|
||||
} else
|
||||
m_Query[key].emplace_back(std::move(value));
|
||||
m_Query.emplace_back(Utility::UnescapeString(key), std::move(value));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "base/array.hpp"
|
||||
#include "base/value.hpp"
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace icinga
|
||||
|
@ -53,9 +54,7 @@ public:
|
|||
String GetHost() const;
|
||||
String GetPort() const;
|
||||
const std::vector<String>& GetPath() const;
|
||||
const std::map<String, std::vector<String> >& GetQuery() const;
|
||||
String GetQueryElement(const String& name) const;
|
||||
const std::vector<String>& GetQueryElements(const String& name) const;
|
||||
const std::vector<std::pair<String, String>>& GetQuery() const;
|
||||
String GetFragment() const;
|
||||
|
||||
void SetScheme(const String& scheme);
|
||||
|
@ -64,11 +63,10 @@ public:
|
|||
void SetHost(const String& host);
|
||||
void SetPort(const String& port);
|
||||
void SetPath(const std::vector<String>& path);
|
||||
void SetQuery(const std::map<String, std::vector<String> >& query);
|
||||
void SetQuery(const std::vector<std::pair<String, String>>& query);
|
||||
void SetArrayFormatUseBrackets(bool useBrackets = true);
|
||||
|
||||
void AddQueryElement(const String& name, const String& query);
|
||||
void SetQueryElements(const String& name, const std::vector<String>& query);
|
||||
void SetFragment(const String& fragment);
|
||||
|
||||
private:
|
||||
|
@ -78,7 +76,7 @@ private:
|
|||
String m_Host;
|
||||
String m_Port;
|
||||
std::vector<String> m_Path;
|
||||
std::map<String, std::vector<String> > m_Query;
|
||||
std::vector<std::pair<String, String>> m_Query;
|
||||
bool m_ArrayFormatUseBrackets;
|
||||
String m_Fragment;
|
||||
|
||||
|
|
|
@ -53,31 +53,50 @@ BOOST_AUTO_TEST_CASE(get_and_set)
|
|||
|
||||
BOOST_CHECK(url->Format(false, true) == "ftp://Horst:Seehofer@koenigreich.bayern:1918/path/to/m%C3%BCnchen");
|
||||
|
||||
std::map<String, std::vector<String> > m;
|
||||
std::vector<String> v1 { "hip", "hip", "hurra" };
|
||||
std::vector<String> v2 { "äü^ä+#ül-" };
|
||||
std::vector<String> v3 { "1", "2" };
|
||||
m.insert(std::make_pair("shout", v1));
|
||||
m.insert(std::make_pair("sonderzeichen", v2));
|
||||
url->SetQuery(m);
|
||||
url->SetQueryElements("count", v3);
|
||||
url->SetQuery({
|
||||
{"shout", "hip"},
|
||||
{"shout", "hip"},
|
||||
{"shout", "hurra"},
|
||||
{"sonderzeichen", "äü^ä+#ül-"}
|
||||
});
|
||||
url->AddQueryElement("count", "3");
|
||||
|
||||
std::map<String, std::vector<String> > mn = url->GetQuery();
|
||||
BOOST_CHECK(mn["shout"][0] == v1[0]);
|
||||
BOOST_CHECK(mn["sonderzeichen"][0] == v2[0]);
|
||||
BOOST_CHECK(mn["count"][2] == "3");
|
||||
auto mn (url->GetQuery());
|
||||
|
||||
BOOST_CHECK(mn.size() == 5);
|
||||
|
||||
BOOST_CHECK(mn[0].first == "shout");
|
||||
BOOST_CHECK(mn[0].second == "hip");
|
||||
|
||||
BOOST_CHECK(mn[1].first == "shout");
|
||||
BOOST_CHECK(mn[1].second == "hip");
|
||||
|
||||
BOOST_CHECK(mn[2].first == "shout");
|
||||
BOOST_CHECK(mn[2].second == "hurra");
|
||||
|
||||
BOOST_CHECK(mn[3].first == "sonderzeichen");
|
||||
BOOST_CHECK(mn[3].second == "äü^ä+#ül-");
|
||||
|
||||
BOOST_CHECK(mn[4].first == "count");
|
||||
BOOST_CHECK(mn[4].second == "3");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(parameters)
|
||||
{
|
||||
Url::Ptr url = new Url("https://icinga.com/hya/?rain=karl&rair=robert&foo[]=bar");
|
||||
Url::Ptr url = new Url("https://icinga.com/hya/?rair=robert&rain=karl&foo[]=bar");
|
||||
|
||||
BOOST_CHECK(url->GetQueryElement("rair") == "robert");
|
||||
BOOST_CHECK(url->GetQueryElement("rain") == "karl");
|
||||
std::vector<String> test = url->GetQueryElements("foo");
|
||||
BOOST_CHECK(test.size() == 1);
|
||||
BOOST_CHECK(test[0] == "bar");
|
||||
auto query (url->GetQuery());
|
||||
|
||||
BOOST_CHECK(query.size() == 3);
|
||||
|
||||
BOOST_CHECK(query[0].first == "rair");
|
||||
BOOST_CHECK(query[0].second == "robert");
|
||||
|
||||
BOOST_CHECK(query[1].first == "rain");
|
||||
BOOST_CHECK(query[1].second == "karl");
|
||||
|
||||
BOOST_CHECK(query[2].first == "foo");
|
||||
BOOST_CHECK(query[2].second == "bar");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(format)
|
||||
|
|
Loading…
Reference in New Issue