diff options
-rw-r--r-- | platform/default/sqlite_cache.cpp | 60 | ||||
-rw-r--r-- | src/mbgl/util/mapbox.cpp | 51 | ||||
-rw-r--r-- | src/mbgl/util/mapbox.hpp | 6 | ||||
-rw-r--r-- | test/miscellaneous/mapbox.cpp | 56 |
4 files changed, 120 insertions, 53 deletions
diff --git a/platform/default/sqlite_cache.cpp b/platform/default/sqlite_cache.cpp index 8863c151e7..46df7ed2af 100644 --- a/platform/default/sqlite_cache.cpp +++ b/platform/default/sqlite_cache.cpp @@ -5,6 +5,7 @@ #include <mbgl/util/compression.hpp> #include <mbgl/util/io.hpp> #include <mbgl/util/thread.hpp> +#include <mbgl/util/mapbox.hpp> #include <mbgl/platform/log.hpp> #include "sqlite3.hpp" @@ -12,53 +13,6 @@ namespace mbgl { -std::string removeAccessTokenFromURL(const std::string &url) { - const size_t token_start = url.find("access_token="); - // Ensure that token exists, isn't at the front and is preceded by either & or ?. - if (token_start == std::string::npos || token_start == 0 || !(url[token_start - 1] == '&' || url[token_start - 1] == '?')) { - return url; - } - - const size_t token_end = url.find_first_of('&', token_start); - if (token_end == std::string::npos) { - // The token is the last query argument. We slice away the "&access_token=..." part - return url.substr(0, token_start - 1); - } else { - // We slice away the "access_token=...&" part. - return url.substr(0, token_start) + url.substr(token_end + 1); - } -} - -std::string convertMapboxDomainsToProtocol(const std::string &url) { - const size_t protocol_separator = url.find("://"); - if (protocol_separator == std::string::npos) { - return url; - } - - const std::string protocol = url.substr(0, protocol_separator); - if (!(protocol == "http" || protocol == "https")) { - return url; - } - - const size_t domain_begin = protocol_separator + 3; - const size_t path_separator = url.find("/", domain_begin); - if (path_separator == std::string::npos) { - return url; - } - - const std::string domain = url.substr(domain_begin, path_separator - domain_begin); - if (domain.find(".tiles.mapbox.com") != std::string::npos) { - return "mapbox://" + url.substr(path_separator + 1); - } else { - return url; - } -} - -std::string unifyMapboxURLs(const std::string &url) { - return removeAccessTokenFromURL(convertMapboxDomainsToProtocol(url)); -} - - using namespace mapbox::sqlite; SQLiteCache::SQLiteCache(const std::string& path_) @@ -154,8 +108,8 @@ void SQLiteCache::Impl::get(const Resource &resource, Callback callback) { getStmt->reset(); } - const std::string unifiedURL = unifyMapboxURLs(resource.url); - getStmt->bind(1, unifiedURL.c_str()); + const auto canonicalURL = util::mapbox::canonicalURL(resource.url); + getStmt->bind(1, canonicalURL.c_str()); if (getStmt->run()) { // There is data. auto response = std::make_unique<Response>(); @@ -208,8 +162,8 @@ void SQLiteCache::Impl::put(const Resource& resource, std::shared_ptr<const Resp putStmt->reset(); } - const std::string unifiedURL = unifyMapboxURLs(resource.url); - putStmt->bind(1 /* url */, unifiedURL.c_str()); + const auto canonicalURL = util::mapbox::canonicalURL(resource.url); + putStmt->bind(1 /* url */, canonicalURL.c_str()); putStmt->bind(2 /* status */, int(response->status)); putStmt->bind(3 /* kind */, int(resource.kind)); putStmt->bind(4 /* modified */, response->modified); @@ -255,9 +209,9 @@ void SQLiteCache::Impl::refresh(const Resource& resource, int64_t expires) { refreshStmt->reset(); } - const std::string unifiedURL = unifyMapboxURLs(resource.url); + const auto canonicalURL = util::mapbox::canonicalURL(resource.url); refreshStmt->bind(1, int64_t(expires)); - refreshStmt->bind(2, unifiedURL.c_str()); + refreshStmt->bind(2, canonicalURL.c_str()); refreshStmt->run(); } catch (mapbox::sqlite::Exception& ex) { Log::Error(Event::Database, ex.code, ex.what()); diff --git a/src/mbgl/util/mapbox.cpp b/src/mbgl/util/mapbox.cpp index 70587ac5ad..9a97f281d9 100644 --- a/src/mbgl/util/mapbox.cpp +++ b/src/mbgl/util/mapbox.cpp @@ -118,6 +118,57 @@ std::string normalizeTileURL(const std::string& url, const std::string& sourceUR return normalizedURL; } + +std::string removeAccessTokenFromURL(const std::string &url) { + const size_t token_start = url.find("access_token="); + // Ensure that token exists, isn't at the front and is preceded by either & or ?. + if (token_start == std::string::npos || token_start == 0 || !(url[token_start - 1] == '&' || url[token_start - 1] == '?')) { + return url; + } + + const size_t token_end = url.find_first_of('&', token_start); + if (token_end == std::string::npos) { + // The token is the last query argument. We slice away the "&access_token=..." part + return url.substr(0, token_start - 1); + } else { + // We slice away the "access_token=...&" part. + return url.substr(0, token_start) + url.substr(token_end + 1); + } } + +namespace { + +std::string convertMapboxDomainsToProtocol(const std::string &url) { + const size_t protocol_separator = url.find("://"); + if (protocol_separator == std::string::npos) { + return url; + } + + const std::string protocol = url.substr(0, protocol_separator); + if (!(protocol == "http" || protocol == "https")) { + return url; + } + + const size_t domain_begin = protocol_separator + 3; + const size_t path_separator = url.find("/", domain_begin); + if (path_separator == std::string::npos) { + return url; + } + + const std::string domain = url.substr(domain_begin, path_separator - domain_begin); + if (domain == "api.mapbox.com" || domain.find(".tiles.mapbox.com") != std::string::npos) { + return std::string{ "mapbox://" } + url.substr(path_separator + 1); + } else { + return url; + } } + +} // end namespace + +std::string canonicalURL(const std::string &url) { + return removeAccessTokenFromURL(convertMapboxDomainsToProtocol(url)); } + +} // end namespace mapbox +} // end namespace util +} // end namespace mbgl diff --git a/src/mbgl/util/mapbox.hpp b/src/mbgl/util/mapbox.hpp index 9c24dda0e6..57f87e7959 100644 --- a/src/mbgl/util/mapbox.hpp +++ b/src/mbgl/util/mapbox.hpp @@ -14,6 +14,12 @@ std::string normalizeSpriteURL(const std::string& url, const std::string& access std::string normalizeGlyphsURL(const std::string& url, const std::string& accessToken); std::string normalizeTileURL(const std::string& url, const std::string& sourceURL, SourceType sourceType); +// Canonicalizes Mapbox URLs by removing [a-d] subdomain prefixes, access tokens, and protocol. +// Note that this is close, but not exactly the reverse operation as above, as this retains certain +// information, such as the API version. It is used to cache resources retrieved from the URL, that +// sometimes have multiple valid URLs. +std::string canonicalURL(const std::string &url); + } } } diff --git a/test/miscellaneous/mapbox.cpp b/test/miscellaneous/mapbox.cpp index a0f9208298..1ec48a4196 100644 --- a/test/miscellaneous/mapbox.cpp +++ b/test/miscellaneous/mapbox.cpp @@ -81,3 +81,59 @@ TEST(Mapbox, TileURL) { throw e; } } + +TEST(Mapbox, CanonicalURL) { + using mbgl::util::mapbox::canonicalURL; + EXPECT_EQ( + canonicalURL("https://a.tiles.mapbox.com/v4/" + "mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v6/15/17599/" + "10744.vector.pbf?access_token=pk.kAeslEm93Sjf3mXk." + "vbiF02XnvkPkzlFhGSn2iIm6De3Cxsk5tmips2tvkG8sF"), + "mapbox://v4/mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v6/15/17599/10744.vector.pbf"); + + EXPECT_EQ( + canonicalURL("http://a.tiles.mapbox.com/v4/" + "mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v6/15/17599/" + "10744.vector.pbf?access_token=pk.kAeslEm93Sjf3mXk." + "vbiF02XnvkPkzlFhGSn2iIm6De3Cxsk5tmips2tvkG8sF"), + "mapbox://v4/mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v6/15/17599/10744.vector.pbf"); + + EXPECT_EQ( + canonicalURL("https://b.tiles.mapbox.com/v4/" + "mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v6/15/17599/" + "10744.vector.pbf?access_token=pk.kAeslEm93Sjf3mXk." + "vbiF02XnvkPkzlFhGSn2iIm6De3Cxsk5tmips2tvkG8sF"), + "mapbox://v4/mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v6/15/17599/10744.vector.pbf"); + + EXPECT_EQ( + canonicalURL("http://c.tiles.mapbox.com/v4/" + "mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v6/15/17599/" + "10744.vector.pbf?access_token=pk.kAeslEm93Sjf3mXk." + "vbiF02XnvkPkzlFhGSn2iIm6De3Cxsk5tmips2tvkG8sF"), + "mapbox://v4/mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v6/15/17599/10744.vector.pbf"); + + EXPECT_EQ( + canonicalURL("https://api.mapbox.com/v4/" + "mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v6/15/17599/" + "10744.vector.pbf?access_token=pk.kAeslEm93Sjf3mXk." + "vbiF02XnvkPkzlFhGSn2iIm6De3Cxsk5tmips2tvkG8sF"), + "mapbox://v4/mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v6/15/17599/10744.vector.pbf"); + + EXPECT_EQ( + canonicalURL("http://api.mapbox.com/v4/" + "mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v6/15/17599/" + "10744.vector.pbf"), + "mapbox://v4/mapbox.mapbox-terrain-v2,mapbox.mapbox-streets-v6/15/17599/10744.vector.pbf"); + + EXPECT_EQ(canonicalURL("https://api.mapbox.com/fonts/v1/mapbox/" + "DIN%20Offc%20Pro%20Italic%2cArial%20Unicode%20MS%20Regular/" + "0-255.pbf?access_token=pk.kAeslEm93Sjf3mXk." + "vbiF02XnvkPkzlFhGSn2iIm6De3Cxsk5tmips2tvkG8sF"), + "mapbox://fonts/v1/mapbox/DIN%20Offc%20Pro%20Italic%2cArial%20Unicode%20MS%20Regular/" + "0-255.pbf"); + + EXPECT_EQ(canonicalURL("https://api.mapbox.com/styles/v1/mapbox/streets-v8/" + "sprite.json?access_token=pk.kAeslEm93Sjf3mXk." + "vbiF02XnvkPkzlFhGSn2iIm6De3Cxsk5tmips2tvkG8sF"), + "mapbox://styles/v1/mapbox/streets-v8/sprite.json"); +} |