From 025375ad0b365a06e0742b92fecc9bc538b5a6e0 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 29 Jan 2016 17:49:22 -0800 Subject: [core] Cache with mapbox:// tile URLs --- src/mbgl/style/style_parser.cpp | 4 +- src/mbgl/util/mapbox.cpp | 87 ++++++++++++++--------------------------- src/mbgl/util/mapbox.hpp | 9 ++--- 3 files changed, 35 insertions(+), 65 deletions(-) (limited to 'src/mbgl') diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/style_parser.cpp index e3470e45d3..50276c8f5b 100644 --- a/src/mbgl/style/style_parser.cpp +++ b/src/mbgl/style/style_parser.cpp @@ -269,11 +269,11 @@ std::unique_ptr StyleParser::parseTileJSON(const std::string& json, std::unique_ptr result = StyleParser::parseTileJSON(document); // TODO: Remove this hack by delivering proper URLs in the TileJSON to begin with. - if (type == SourceType::Raster && util::mapbox::isMapboxURL(sourceURL)) { + if (util::mapbox::isMapboxURL(sourceURL)) { std::transform(result->tiles.begin(), result->tiles.end(), result->tiles.begin(), - util::mapbox::normalizeRasterTileURL); + std::bind(util::mapbox::canonicalizeTileURL, std::placeholders::_1, type)); } return result; diff --git a/src/mbgl/util/mapbox.cpp b/src/mbgl/util/mapbox.cpp index d94a9a5f7d..93b2b8521c 100644 --- a/src/mbgl/util/mapbox.cpp +++ b/src/mbgl/util/mapbox.cpp @@ -111,83 +111,56 @@ std::string normalizeGlyphsURL(const std::string& url, const std::string& access return baseURL + "fonts/v1/" + user + "/" + fontstack + "/" + range + "?access_token=" + accessToken; } -std::string normalizeRasterTileURL(const std::string& url) { - std::string::size_type queryIdx = url.rfind("?"); - // Trim off the right end but never touch anything before the extension dot. - std::string urlSansParams((queryIdx == std::string::npos) ? url : url.substr(0, queryIdx)); - - while (!urlSansParams.empty() && isdigit(urlSansParams.back())) { - urlSansParams.pop_back(); - } - - std::string::size_type basenameIdx = url.rfind("/", queryIdx); - std::string::size_type extensionIdx = url.rfind(".", queryIdx); - if (basenameIdx == std::string::npos || extensionIdx == std::string::npos || - basenameIdx > extensionIdx) { - // No file extension: probably not a file name we can tack a ratio onto. +std::string normalizeTileURL(const std::string& url, const std::string& accessToken) { + if (!isMapboxURL(url)) { return url; } - std::string normalizedURL(url); -#if !defined(__ANDROID__) && !defined(__APPLE__) - // Replace PNG with WebP. - if (normalizedURL.compare(extensionIdx + 1, 3, "png") == 0) { - normalizedURL.replace(extensionIdx + 1, 3, "webp"); - } -#endif // !defined(__ANDROID__) && !defined(__APPLE__) - normalizedURL.insert(extensionIdx, "{ratio}"); - return normalizedURL; + return baseURL + "v4/" + url.substr(sizeof("mapbox://tiles/") - 1) + "?access_token=" + accessToken; } - -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] == '?')) { +std::string canonicalizeTileURL(const std::string& url, SourceType type) { + auto tilesetStartIdx = url.find("/v4/"); + if (tilesetStartIdx == std::string::npos) { 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); - } -} + tilesetStartIdx += sizeof("/v4/") - 1; -namespace { - -std::string convertMapboxDomainsToProtocol(const std::string &url) { - const size_t protocol_separator = url.find("://"); - if (protocol_separator == std::string::npos) { + auto tilesetEndIdx = url.find("/", tilesetStartIdx); + if (tilesetEndIdx == std::string::npos) { return url; } - const std::string protocol = url.substr(0, protocol_separator); - if (!(protocol == "http" || protocol == "https")) { - return url; + auto queryIdx = url.rfind("?"); + if (queryIdx == std::string::npos) { + queryIdx = url.length(); } - 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; + auto basenameIdx = url.rfind("/", queryIdx); + if (basenameIdx == std::string::npos || basenameIdx == queryIdx - 1) { + basenameIdx = url.length(); + } else { + basenameIdx += 1; } - 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 { + auto extensionIdx = url.find(".", basenameIdx); + if (extensionIdx == std::string::npos || extensionIdx == queryIdx - 1) { return url; } -} -} // end namespace + auto tileset = url.substr(tilesetStartIdx, tilesetEndIdx - tilesetStartIdx); + auto extension = url.substr(extensionIdx + 1, queryIdx - extensionIdx - 1); + +#if !defined(__ANDROID__) && !defined(__APPLE__) + // Replace PNG with WebP. + if (extension == "png") { + extension = "webp"; + } +#endif // !defined(__ANDROID__) && !defined(__APPLE__) -std::string canonicalURL(const std::string &url) { - return removeAccessTokenFromURL(convertMapboxDomainsToProtocol(url)); + return "mapbox://tiles/" + tileset + "/{z}/{x}/{y}" + + (type == SourceType::Raster ? "{ratio}" : "") + "." + extension; } } // end namespace mapbox diff --git a/src/mbgl/util/mapbox.hpp b/src/mbgl/util/mapbox.hpp index 3c44d704c7..c03916ff63 100644 --- a/src/mbgl/util/mapbox.hpp +++ b/src/mbgl/util/mapbox.hpp @@ -14,13 +14,10 @@ std::string normalizeSourceURL(const std::string& url, const std::string& access std::string normalizeStyleURL(const std::string& url, const std::string& accessToken); std::string normalizeSpriteURL(const std::string& url, const std::string& accessToken); std::string normalizeGlyphsURL(const std::string& url, const std::string& accessToken); -std::string normalizeRasterTileURL(const std::string& url); +std::string normalizeTileURL(const std::string& url, const std::string& accessToken); -// 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); +// Return a "mapbox://tiles/..." URL (suitable for normalizeTileURL) for the given Mapbox tile URL. +std::string canonicalizeTileURL(const std::string& url, SourceType); } // namespace mapbox } // namespace util -- cgit v1.2.1