Skip to content

Commit 11140f0

Browse files
authored
Merge pull request #744 from CesiumGS/extract-uri-value
Extract Value From URI
2 parents daae030 + d3f74aa commit 11140f0

File tree

5 files changed

+108
-1
lines changed

5 files changed

+108
-1
lines changed

CesiumIonClient/include/CesiumIonClient/Connection.h

+5
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ class CESIUMASYNC_API Connection {
105105
const std::string& ionApiUrl = "https://api.cesium.com/",
106106
const std::string& ionAuthorizeUrl = "https://ion.cesium.com/oauth");
107107

108+
static CesiumAsync::Future<std::optional<std::string>> getApiUrl(
109+
const CesiumAsync::AsyncSystem& asyncSystem,
110+
const std::shared_ptr<CesiumAsync::IAssetAccessor>& pAssetAccessor,
111+
const std::string& ionUrl);
112+
108113
/**
109114
* @brief Creates a connection to Cesium ion using the provided access token.
110115
*

CesiumIonClient/src/Connection.cpp

+47-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <rapidjson/error/en.h>
1616
#include <rapidjson/stringbuffer.h>
1717
#include <rapidjson/writer.h>
18+
#include <uriparser/Uri.h>
1819

1920
#include <thread>
2021

@@ -134,7 +135,7 @@ std::string createAuthorizationErrorHtml(
134135
authorizeUrl =
135136
Uri::addQuery(authorizeUrl, "client_id", std::to_string(clientID));
136137
authorizeUrl =
137-
Uri::addQuery(authorizeUrl, "scope", joinToString(scopes, " "));
138+
Uri::addQuery(authorizeUrl, "scope", joinToString(scopes, "%20"));
138139
authorizeUrl = Uri::addQuery(authorizeUrl, "redirect_uri", redirectUrl);
139140
authorizeUrl = Uri::addQuery(authorizeUrl, "state", state);
140141
authorizeUrl = Uri::addQuery(authorizeUrl, "code_challenge_method", "S256");
@@ -373,6 +374,51 @@ Asset jsonToAsset(const rapidjson::Value& item) {
373374

374375
} // namespace
375376

377+
CesiumAsync::Future<std::optional<std::string>>
378+
CesiumIonClient::Connection::getApiUrl(
379+
const CesiumAsync::AsyncSystem& asyncSystem,
380+
const std::shared_ptr<IAssetAccessor>& pAssetAccessor,
381+
const std::string& ionUrl) {
382+
std::string configUrl = Uri::resolve(ionUrl, "config.json");
383+
if (configUrl == "config.json") {
384+
return asyncSystem.createResolvedFuture<std::optional<std::string>>(
385+
std::nullopt);
386+
}
387+
return pAssetAccessor->get(asyncSystem, configUrl)
388+
.thenImmediately([ionUrl](std::shared_ptr<IAssetRequest>&& pRequest) {
389+
const IAssetResponse* pResponse = pRequest->response();
390+
if (pResponse && pResponse->statusCode() >= 200 &&
391+
pResponse->statusCode() < 300) {
392+
rapidjson::Document d;
393+
if (parseJsonObject(pResponse, d) && d.IsObject()) {
394+
const auto itr = d.FindMember("apiHostname");
395+
if (itr != d.MemberEnd() && itr->value.IsString()) {
396+
return std::make_optional<std::string>(itr->value.GetString());
397+
}
398+
}
399+
}
400+
401+
UriUriA newUri;
402+
if (uriParseSingleUriA(&newUri, ionUrl.c_str(), nullptr) !=
403+
URI_SUCCESS) {
404+
return std::optional<std::string>();
405+
}
406+
407+
std::string hostName =
408+
std::string(newUri.hostText.first, newUri.hostText.afterLast);
409+
std::string scheme =
410+
std::string(newUri.scheme.first, newUri.scheme.afterLast);
411+
412+
uriFreeUriMembersA(&newUri);
413+
414+
return std::make_optional<std::string>(
415+
scheme + "://api." + hostName + '/');
416+
})
417+
.catchImmediately([](std::exception&&) {
418+
return std::optional<std::string>(std::nullopt);
419+
});
420+
}
421+
376422
CesiumAsync::Future<Response<Assets>> Connection::assets() const {
377423
return this->_pAssetAccessor
378424
->get(

CesiumUtility/include/CesiumUtility/Uri.h

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ class Uri final {
1414
const std::string& uri,
1515
const std::string& key,
1616
const std::string& value);
17+
static std::string
18+
getQueryValue(const std::string& uri, const std::string& key);
1719

1820
typedef std::string
1921
SubstitutionCallbackSignature(const std::string& placeholder);

CesiumUtility/src/Uri.cpp

+32
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <uriparser/Uri.h>
44

5+
#include <cstring>
56
#include <stdexcept>
67

78
namespace CesiumUtility {
@@ -100,6 +101,37 @@ std::string Uri::addQuery(
100101
// uriFreeUriMembersA(&baseUri);
101102
}
102103

104+
std::string Uri::getQueryValue(const std::string& url, const std::string& key) {
105+
UriUriA uri;
106+
if (uriParseSingleUriA(&uri, url.c_str(), nullptr) != URI_SUCCESS) {
107+
return "";
108+
}
109+
UriQueryListA* queryList;
110+
int itemCount;
111+
if (uriDissectQueryMallocA(
112+
&queryList,
113+
&itemCount,
114+
uri.query.first,
115+
uri.query.afterLast) != URI_SUCCESS) {
116+
uriFreeUriMembersA(&uri);
117+
return "";
118+
}
119+
UriQueryListA* p = queryList;
120+
while (p) {
121+
if (p->key && std::strcmp(p->key, key.c_str()) == 0) {
122+
std::string value = p->value ? p->value : "";
123+
uriUnescapeInPlaceA(value.data());
124+
uriFreeQueryListA(queryList);
125+
uriFreeUriMembersA(&uri);
126+
return value;
127+
}
128+
p = p->next;
129+
}
130+
uriFreeQueryListA(queryList);
131+
uriFreeUriMembersA(&uri);
132+
return "";
133+
}
134+
103135
std::string Uri::substituteTemplateParameters(
104136
const std::string& templateUri,
105137
const std::function<SubstitutionCallbackSignature>& substitutionCallback) {
+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include "CesiumUtility/Uri.h"
2+
3+
#include <catch2/catch.hpp>
4+
5+
using namespace CesiumUtility;
6+
7+
TEST_CASE("Uri::getQueryValue") {
8+
std::string url = "https://example.com/?name=John&age=25";
9+
CHECK(Uri::getQueryValue(url, "name") == "John");
10+
CHECK(Uri::getQueryValue(url, "age") == std::to_string(25));
11+
CHECK(Uri::getQueryValue(url, "gender") == "");
12+
CHECK(Uri::getQueryValue(url, "") == "");
13+
CHECK(Uri::getQueryValue("", "name") == "");
14+
CHECK(
15+
Uri::getQueryValue(
16+
"https://example.com/?name=John&name=Jane&age=25",
17+
"name") == "John");
18+
CHECK(
19+
Uri::getQueryValue(
20+
"https://example.com/?name=John%20Doe&age=25",
21+
"name") == "John Doe");
22+
}

0 commit comments

Comments
 (0)