Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
Support v8 sprite, glyph, and style mapbox:// urls
Browse files Browse the repository at this point in the history
  • Loading branch information
Lucas Wojciechowski committed Aug 21, 2015
1 parent b7a4000 commit e976629
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 35 deletions.
4 changes: 2 additions & 2 deletions include/mbgl/storage/resource.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ struct Resource {
Source,
Tile,
Glyphs,
JSON,
Image
SpriteImage,
SpriteJSON
};

const Kind kind;
Expand Down
2 changes: 1 addition & 1 deletion platform/default/sqlite_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ void SQLiteCache::Impl::put(const Resource& resource, std::shared_ptr<const Resp
putStmt->bind(6 /* expires */, response->expires);

std::string data;
if (resource.kind != Resource::Image) {
if (resource.kind != Resource::SpriteImage) {
// Do not compress images, since they are typically compressed already.
data = util::compress(response->data);
}
Expand Down
5 changes: 3 additions & 2 deletions src/mbgl/map/sprite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <mbgl/util/raster.hpp>
#include <mbgl/util/thread.hpp>
#include <mbgl/util/uv_detail.hpp>
#include <mbgl/util/mapbox.hpp>

#include <rapidjson/document.h>

Expand Down Expand Up @@ -49,7 +50,7 @@ Sprite::Sprite(const std::string& baseUrl, float pixelRatio_)
loader = std::make_unique<Loader>();

FileSource* fs = util::ThreadContext::getFileSource();
loader->jsonRequest = fs->request({ Resource::Kind::JSON, jsonURL }, util::RunLoop::getLoop(),
loader->jsonRequest = fs->request({ Resource::Kind::SpriteJSON, jsonURL }, util::RunLoop::getLoop(),
[this, jsonURL](const Response& res) {
loader->jsonRequest = nullptr;
if (res.status == Response::Successful) {
Expand All @@ -65,7 +66,7 @@ Sprite::Sprite(const std::string& baseUrl, float pixelRatio_)
});

loader->spriteRequest =
fs->request({ Resource::Kind::Image, spriteURL }, util::RunLoop::getLoop(),
fs->request({ Resource::Kind::SpriteImage, spriteURL }, util::RunLoop::getLoop(),
[this, spriteURL](const Response& res) {
loader->spriteRequest = nullptr;
if (res.status == Response::Successful) {
Expand Down
5 changes: 5 additions & 0 deletions src/mbgl/storage/default_file_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ Request* DefaultFileSource::request(const Resource& resource,
url = util::mapbox::normalizeGlyphsURL(resource.url, accessToken);
break;

case Resource::Kind::SpriteImage:
case Resource::Kind::SpriteJSON:
url = util::mapbox::normalizeSpriteURL(resource.url, accessToken);
break;

default:
url = resource.url;
}
Expand Down
83 changes: 57 additions & 26 deletions src/mbgl/util/mapbox.cpp
Original file line number Diff line number Diff line change
@@ -1,59 +1,90 @@
#include <mbgl/util/mapbox.hpp>

#include <stdexcept>
#include <vector>

namespace mbgl {
namespace util {
namespace mapbox {

const std::string mapbox = "mapbox://";
const std::string protocol = "mapbox://";
const std::string baseURL = "https://api.mapbox.com/";

std::string normalizeURL(const std::string& url, const std::string& pathPrefix, const std::string& accessToken) {
if (accessToken.empty())
throw std::runtime_error("You must provide a Mapbox API access token for Mapbox tile sources");
bool isMapboxURL(const std::string& url) {
return url.compare(0, protocol.length(), protocol) == 0;
}

return std::string("https://api.tiles.mapbox.com")
+ pathPrefix
+ url.substr(mapbox.length())
+ "?access_token="
+ accessToken;
std::vector<std::string> getMapboxURLPathname(const std::string& url) {
std::vector<std::string> pathname;
std::size_t startIndex = protocol.length();
while (startIndex < url.length()) {
std::size_t endIndex = url.find("/", startIndex);
if (endIndex == std::string::npos) endIndex = url.length();
pathname.push_back(url.substr(startIndex, endIndex - startIndex));
startIndex = endIndex + 1;
}
return pathname;
}

std::string normalizeSourceURL(const std::string& url, const std::string& accessToken) {
if (url.compare(0, mapbox.length(), mapbox) != 0)
if (!isMapboxURL(url)) {
return url;
}

std::string result = normalizeURL(url + ".json", "/v4/", accessToken);

// TileJSON requests need a secure flag appended to their URLs so
// that the server knows to send SSL-ified resource references.
result += "&secure";
if (accessToken.empty()) {
throw std::runtime_error("You must provide a Mapbox API access token for Mapbox tile sources");
}

return result;
return baseURL + "v4/" + url.substr(protocol.length()) + ".json?access_token=" + accessToken + "&secure";
}

std::string normalizeStyleURL(const std::string& url, const std::string& accessToken) {
if (url.compare(0, mapbox.length(), mapbox) != 0)
if (!isMapboxURL(url)) {
return url;
}

std::vector<std::string> pathname = getMapboxURLPathname(url);
std::string user = pathname[1];
std::string id = pathname[2];
bool isDraft = pathname.size() > 3;
return baseURL + "styles/v1/" + user + "/" + id + (isDraft ? "/draft" : "") + "?access_token=" + accessToken;
}

std::string normalizeSpriteURL(const std::string& url, const std::string& accessToken) {
if (!isMapboxURL(url)) {
return url;
}

const std::string user = url.substr(mapbox.length(), url.find('.') - mapbox.length());
std::vector<std::string> pathname = getMapboxURLPathname(url);
std::string user = pathname[1];
bool isDraft = pathname.size() > 3;

return normalizeURL(url, "/styles/v1/" + user + "/", accessToken);
std::string id, extension;
if (isDraft) {
size_t index = pathname[3].find_first_of("@.");
id = pathname[2];
extension = pathname[3].substr(index);
} else {
size_t index = pathname[2].find_first_of("@.");
id = pathname[2].substr(0, index);
extension = pathname[2].substr(index);
}

return baseURL + "styles/v1/" + user + "/" + id + "/" + (isDraft ? "draft/" : "") + "sprite" + extension + "?access_token=" + accessToken;
}

std::string normalizeGlyphsURL(const std::string& url, const std::string& accessToken) {
if (url.compare(0, mapbox.length(), mapbox) != 0) {
if (!isMapboxURL(url)) {
return url;
} else {
const std::string prefix = "mapbox://fonts/";
const std::string user = url.substr(prefix.length(), url.find("/", prefix.length()) - prefix.length());
return normalizeURL("mapbox://" + user + "/{fontstack}/{range}.pbf", "/fonts/v1/", accessToken);
}

std::vector<std::string> pathname = getMapboxURLPathname(url);
std::string user = pathname[1];
return baseURL + "fonts/v1/" + user + "/{fontstack}/{range}.pbf?access_token=" + accessToken;
}

std::string normalizeTileURL(const std::string& url, const std::string& sourceURL, SourceType sourceType) {
if (sourceURL.empty() || sourceURL.compare(0, mapbox.length(), mapbox) != 0 ||
sourceType != SourceType::Raster) {
if (sourceURL.empty() || !isMapboxURL(sourceURL) || sourceType != SourceType::Raster) {
return url;
}

Expand Down
1 change: 1 addition & 0 deletions src/mbgl/util/mapbox.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ namespace mapbox {

std::string normalizeSourceURL(const std::string& url, const std::string& accessToken);
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 normalizeTileURL(const std::string& url, const std::string& sourceURL, SourceType sourceType);

Expand Down
16 changes: 12 additions & 4 deletions test/miscellaneous/mapbox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,29 @@
using namespace mbgl;

TEST(Mapbox, SourceURL) {
EXPECT_EQ(mbgl::util::mapbox::normalizeSourceURL("mapbox://user.map", "key"), "https://api.tiles.mapbox.com/v4/user.map.json?access_token=key&secure");
EXPECT_EQ(mbgl::util::mapbox::normalizeSourceURL("mapbox://user.map", "token"), "https://api.tiles.mapbox.com/v4/user.map.json?access_token=token&secure");
EXPECT_EQ(mbgl::util::mapbox::normalizeSourceURL("mapbox://user.map", "key"), "https://api.mapbox.com/v4/user.map.json?access_token=key&secure");
EXPECT_EQ(mbgl::util::mapbox::normalizeSourceURL("mapbox://user.map", "token"), "https://api.mapbox.com/v4/user.map.json?access_token=token&secure");
EXPECT_THROW(mbgl::util::mapbox::normalizeSourceURL("mapbox://user.map", ""), std::runtime_error);
}

TEST(Mapbox, GlyphsURL) {
EXPECT_EQ(mbgl::util::mapbox::normalizeGlyphsURL("mapbox://fonts/boxmap/{fontstack}/{range}.pbf", "key"), "https://api.tiles.mapbox.com/fonts/v1/boxmap/{fontstack}/{range}.pbf?access_token=key");
EXPECT_EQ(mbgl::util::mapbox::normalizeGlyphsURL("mapbox://fonts/boxmap/{fontstack}/{range}.pbf", "key"), "https://api.mapbox.com/fonts/v1/boxmap/{fontstack}/{range}.pbf?access_token=key");
EXPECT_EQ(mbgl::util::mapbox::normalizeGlyphsURL("http://path", "key"), "http://path");
}

TEST(Mapbox, StyleURL) {
EXPECT_EQ(mbgl::util::mapbox::normalizeStyleURL("mapbox://user.style", "key"), "https://api.tiles.mapbox.com/styles/v1/user/user.style?access_token=key");
EXPECT_EQ(mbgl::util::mapbox::normalizeStyleURL("mapbox://styles/user/style", "key"), "https://api.mapbox.com/styles/v1/user/style?access_token=key");
EXPECT_EQ(mbgl::util::mapbox::normalizeStyleURL("mapbox://styles/user/style/draft", "key"), "https://api.mapbox.com/styles/v1/user/style/draft?access_token=key");
EXPECT_EQ(mbgl::util::mapbox::normalizeStyleURL("http://path", "key"), "http://path");
}

TEST(Mapbox, SpriteURL) {
EXPECT_EQ(mbgl::util::mapbox::normalizeSpriteURL("map/box/[email protected]", "key"), "map/box/[email protected]");
EXPECT_EQ(mbgl::util::mapbox::normalizeSpriteURL("mapbox://sprites/mapbox/streets-v8.json", "key"), "https://api.mapbox.com/styles/v1/mapbox/streets-v8/sprite.json?access_token=key");
EXPECT_EQ(mbgl::util::mapbox::normalizeSpriteURL("mapbox://sprites/mapbox/[email protected]", "key"), "https://api.mapbox.com/styles/v1/mapbox/streets-v8/[email protected]?access_token=key");
EXPECT_EQ(mbgl::util::mapbox::normalizeSpriteURL("mapbox://sprites/mapbox/streets-v8/[email protected]", "key"), "https://api.mapbox.com/styles/v1/mapbox/streets-v8/draft/[email protected]?access_token=key");
}

TEST(Mapbox, TileURL) {
try {
EXPECT_EQ(mbgl::util::mapbox::normalizeTileURL("http://path.png/tile.png", "mapbox://user.map", SourceType::Raster), "http://path.png/tile{ratio}.png");
Expand Down

0 comments on commit e976629

Please sign in to comment.