Merge 127a4465c9 into 83e20b7a4e
This commit is contained in:
commit
c7a1dccf57
5 changed files with 101 additions and 50 deletions
|
|
@ -180,7 +180,7 @@ module.exports = function(options, repo, params, id, styles) {
|
||||||
info.tiles = utils.getTileUrls(req, info.tiles,
|
info.tiles = utils.getTileUrls(req, info.tiles,
|
||||||
'data/' + id, info.format, {
|
'data/' + id, info.format, {
|
||||||
'pbf': options.pbfAlias
|
'pbf': options.pbfAlias
|
||||||
});
|
}, options);
|
||||||
return res.send(info);
|
return res.send(info);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -747,7 +747,7 @@ module.exports = function(options, repo, params, id, dataResolver) {
|
||||||
app.get('/' + id + '.json', function(req, res, next) {
|
app.get('/' + id + '.json', function(req, res, next) {
|
||||||
var info = clone(tileJSON);
|
var info = clone(tileJSON);
|
||||||
info.tiles = utils.getTileUrls(req, info.tiles,
|
info.tiles = utils.getTileUrls(req, info.tiles,
|
||||||
'styles/' + id, info.format);
|
'styles/' + id, info.format, null, options);
|
||||||
return res.send(info);
|
return res.send(info);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,27 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var path = require('path'),
|
var path = require('path'),
|
||||||
fs = require('fs');
|
fs = require('fs'),
|
||||||
|
nodeUrl = require('url'),
|
||||||
|
querystring = require('querystring');
|
||||||
|
|
||||||
var clone = require('clone'),
|
var clone = require('clone'),
|
||||||
express = require('express');
|
express = require('express');
|
||||||
|
|
||||||
|
|
||||||
module.exports = function(options, repo, params, id, reportTiles, reportFont) {
|
module.exports = function (options, repo, params, id, reportTiles, reportFont) {
|
||||||
var app = express().disable('x-powered-by');
|
var app = express().disable('x-powered-by');
|
||||||
|
|
||||||
var styleFile = path.resolve(options.paths.styles, params.style);
|
var styleFile = path.resolve(options.paths.styles, params.style);
|
||||||
|
|
||||||
var styleJSON = clone(require(styleFile));
|
var styleJSON = clone(require(styleFile));
|
||||||
Object.keys(styleJSON.sources).forEach(function(name) {
|
Object.keys(styleJSON.sources).forEach(function (name) {
|
||||||
var source = styleJSON.sources[name];
|
var source = styleJSON.sources[name];
|
||||||
var url = source.url;
|
var url = source.url;
|
||||||
if (url && url.lastIndexOf('mbtiles:', 0) === 0) {
|
if (url && url.lastIndexOf('mbtiles:', 0) === 0) {
|
||||||
var mbtilesFile = url.substring('mbtiles://'.length);
|
var mbtilesFile = url.substring('mbtiles://'.length);
|
||||||
var fromData = mbtilesFile[0] == '{' &&
|
var fromData = mbtilesFile[0] == '{' &&
|
||||||
mbtilesFile[mbtilesFile.length - 1] == '}';
|
mbtilesFile[mbtilesFile.length - 1] == '}';
|
||||||
|
|
||||||
if (fromData) {
|
if (fromData) {
|
||||||
mbtilesFile = mbtilesFile.substr(1, mbtilesFile.length - 2);
|
mbtilesFile = mbtilesFile.substr(1, mbtilesFile.length - 2);
|
||||||
|
|
@ -33,7 +35,7 @@ module.exports = function(options, repo, params, id, reportTiles, reportFont) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
styleJSON.layers.forEach(function(obj) {
|
styleJSON.layers.forEach(function (obj) {
|
||||||
if (obj['type'] == 'symbol') {
|
if (obj['type'] == 'symbol') {
|
||||||
var fonts = (obj['layout'] || {})['text-font'];
|
var fonts = (obj['layout'] || {})['text-font'];
|
||||||
if (fonts && fonts.length) {
|
if (fonts && fonts.length) {
|
||||||
|
|
@ -45,51 +47,94 @@ module.exports = function(options, repo, params, id, reportTiles, reportFont) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var normalizeSpritePath = function (intermediatePath) {
|
||||||
|
return path.join(options.paths.sprites,
|
||||||
|
intermediatePath
|
||||||
|
.replace('{style}', path.basename(styleFile, '.json'))
|
||||||
|
.replace('{styleJsonFolder}', path.relative(options.paths.sprites, path.dirname(styleFile)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
var spritePath;
|
var spritePath;
|
||||||
|
|
||||||
var httpTester = /^(http(s)?:)?\/\//;
|
var httpTester = /^(http(s)?:)?\/\//;
|
||||||
|
|
||||||
|
// if the current style JSON has a sprite path referencing some local sprites,
|
||||||
|
// replace placeholders, use that as our sprite path for this style, and
|
||||||
|
// then update the sprite path in the styleJSON to reference the sprite url.
|
||||||
if (styleJSON.sprite && !httpTester.test(styleJSON.sprite)) {
|
if (styleJSON.sprite && !httpTester.test(styleJSON.sprite)) {
|
||||||
spritePath = path.join(options.paths.sprites,
|
spritePath = normalizeSpritePath(styleJSON.sprite);
|
||||||
styleJSON.sprite
|
|
||||||
.replace('{style}', path.basename(styleFile, '.json'))
|
|
||||||
.replace('{styleJsonFolder}', path.relative(options.paths.sprites, path.dirname(styleFile)))
|
|
||||||
);
|
|
||||||
styleJSON.sprite = 'local://styles/' + id + '/sprite';
|
styleJSON.sprite = 'local://styles/' + id + '/sprite';
|
||||||
|
// if there are still sprites for this style, serve them according to the config setting
|
||||||
|
} else if (params.serveSprites && typeof params.serveSprites === 'object') {
|
||||||
|
spritePath = normalizeSpritePath(params.serveSprites.file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (styleJSON.glyphs && !httpTester.test(styleJSON.glyphs)) {
|
if (styleJSON.glyphs && !httpTester.test(styleJSON.glyphs)) {
|
||||||
styleJSON.glyphs = 'local://fonts/{fontstack}/{range}.pbf';
|
styleJSON.glyphs = 'local://fonts/{fontstack}/{range}.pbf';
|
||||||
}
|
}
|
||||||
|
|
||||||
repo[id] = styleJSON;
|
repo[id] = styleJSON;
|
||||||
|
|
||||||
app.get('/' + id + '/style.json', function(req, res, next) {
|
var isWhitelistedUrl = function (url) {
|
||||||
var fixUrl = function(url, opt_nokey, opt_nostyle) {
|
if (!options.auth || !Array.isArray(options.auth.keyDomains) || options.auth.keyDomains.length === 0) {
|
||||||
if (!url || (typeof url !== 'string') || url.indexOf('local://') !== 0) {
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < options.auth.keyDomains.length; i++) {
|
||||||
|
var keyDomain = options.auth.keyDomains[i];
|
||||||
|
if (!keyDomain || (typeof keyDomain !== 'string') || keyDomain.length === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.includes(keyDomain)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
app.get('/' + id + '/style.json', function (req, res, next) {
|
||||||
|
var fixUrl = function (url, opt_nokey, opt_nostyle) {
|
||||||
|
if (!url || (typeof url !== 'string') || (url.indexOf('local://') !== 0 && !isWhitelistedUrl(url))) {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
var queryParams = [];
|
|
||||||
|
var queryParams = {};
|
||||||
if (!opt_nostyle && global.addStyleParam) {
|
if (!opt_nostyle && global.addStyleParam) {
|
||||||
queryParams.push('style=' + id);
|
queryParams.style = id;
|
||||||
}
|
}
|
||||||
if (!opt_nokey && req.query.key) {
|
if (!opt_nokey && req.query[options.auth.keyName]) {
|
||||||
queryParams.unshift('key=' + req.query.key);
|
queryParams[options.auth.keyName] = req.query[options.auth.keyName];
|
||||||
}
|
}
|
||||||
var query = '';
|
|
||||||
if (queryParams.length) {
|
if (url.indexOf('local://') === 0) {
|
||||||
query = '?' + queryParams.join('&');
|
var query = querystring.stringify(queryParams);
|
||||||
}
|
if (query.length) {
|
||||||
return url.replace(
|
query = '?' + query;
|
||||||
|
}
|
||||||
|
|
||||||
|
return url.replace(
|
||||||
'local://', req.protocol + '://' + req.headers.host + '/') + query;
|
'local://', req.protocol + '://' + req.headers.host + '/') + query;
|
||||||
|
} else { // whitelisted url. might have existing parameters
|
||||||
|
var parsedUrl = nodeUrl.parse(url);
|
||||||
|
var parsedQS = querystring.parse(parsedUrl.query);
|
||||||
|
var newParams = Object.assign(parsedQS, queryParams);
|
||||||
|
parsedUrl.search = querystring.stringify(parsedQS);
|
||||||
|
return querystring.unescape(nodeUrl.format(parsedUrl));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var styleJSON_ = clone(styleJSON);
|
var styleJSON_ = clone(styleJSON);
|
||||||
Object.keys(styleJSON_.sources).forEach(function(name) {
|
Object.keys(styleJSON_.sources).forEach(function (name) {
|
||||||
var source = styleJSON_.sources[name];
|
var source = styleJSON_.sources[name];
|
||||||
source.url = fixUrl(source.url);
|
source.url = fixUrl(source.url);
|
||||||
});
|
});
|
||||||
// mapbox-gl-js viewer cannot handle sprite urls with query
|
// mapbox-gl-js viewer cannot handle sprite urls with query
|
||||||
if (styleJSON_.sprite) {
|
if (styleJSON_.sprite) {
|
||||||
styleJSON_.sprite = fixUrl(styleJSON_.sprite, true, true);
|
var forceKeyParameter = options.auth.forceSpriteKey === true;
|
||||||
|
styleJSON_.sprite = fixUrl(styleJSON_.sprite, !forceKeyParameter, true);
|
||||||
}
|
}
|
||||||
if (styleJSON_.glyphs) {
|
if (styleJSON_.glyphs) {
|
||||||
styleJSON_.glyphs = fixUrl(styleJSON_.glyphs, false, true);
|
styleJSON_.glyphs = fixUrl(styleJSON_.glyphs, false, true);
|
||||||
|
|
@ -98,24 +143,24 @@ module.exports = function(options, repo, params, id, reportTiles, reportFont) {
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/' + id + '/sprite:scale(@[23]x)?\.:format([\\w]+)',
|
app.get('/' + id + '/sprite:scale(@[23]x)?\.:format([\\w]+)',
|
||||||
function(req, res, next) {
|
function (req, res, next) {
|
||||||
if (!spritePath) {
|
if (!spritePath) {
|
||||||
return res.status(404).send('File not found');
|
|
||||||
}
|
|
||||||
var scale = req.params.scale,
|
|
||||||
format = req.params.format;
|
|
||||||
var filename = spritePath + (scale || '') + '.' + format;
|
|
||||||
return fs.readFile(filename, function(err, data) {
|
|
||||||
if (err) {
|
|
||||||
console.log('Sprite load error:', filename);
|
|
||||||
return res.status(404).send('File not found');
|
return res.status(404).send('File not found');
|
||||||
} else {
|
|
||||||
if (format == 'json') res.header('Content-type', 'application/json');
|
|
||||||
if (format == 'png') res.header('Content-type', 'image/png');
|
|
||||||
return res.send(data);
|
|
||||||
}
|
}
|
||||||
|
var scale = req.params.scale,
|
||||||
|
format = req.params.format;
|
||||||
|
var filename = spritePath + (scale || '') + '.' + format;
|
||||||
|
return fs.readFile(filename, function (err, data) {
|
||||||
|
if (err) {
|
||||||
|
console.log('Sprite load error:', filename);
|
||||||
|
return res.status(404).send('File not found');
|
||||||
|
} else {
|
||||||
|
if (format == 'json') res.header('Content-type', 'application/json');
|
||||||
|
if (format == 'png') res.header('Content-type', 'image/png');
|
||||||
|
return res.send(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.resolve(app);
|
return Promise.resolve(app);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,12 @@ function start(opts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var options = config.options || {};
|
var options = config.options || {};
|
||||||
|
|
||||||
|
options.auth = options.auth || {};
|
||||||
|
options.auth.keyName = options.auth.keyName || 'key';
|
||||||
|
options.auth.keyDomains = options.auth.keyDomains || [];
|
||||||
|
options.auth.forceSpriteKey = options.auth.forceSpriteKey || false;
|
||||||
|
|
||||||
var paths = options.paths || {};
|
var paths = options.paths || {};
|
||||||
options.paths = paths;
|
options.paths = paths;
|
||||||
paths.root = path.resolve(
|
paths.root = path.resolve(
|
||||||
|
|
@ -212,7 +218,7 @@ function start(opts) {
|
||||||
}
|
}
|
||||||
info.tiles = utils.getTileUrls(req, info.tiles, path, info.format, {
|
info.tiles = utils.getTileUrls(req, info.tiles, path, info.format, {
|
||||||
'pbf': options.pbfAlias
|
'pbf': options.pbfAlias
|
||||||
});
|
}, options);
|
||||||
arr.push(info);
|
arr.push(info);
|
||||||
});
|
});
|
||||||
return arr;
|
return arr;
|
||||||
|
|
@ -299,7 +305,7 @@ function start(opts) {
|
||||||
|
|
||||||
var tiles = utils.getTileUrls(
|
var tiles = utils.getTileUrls(
|
||||||
req, style.serving_rendered.tiles,
|
req, style.serving_rendered.tiles,
|
||||||
'styles/' + id, style.serving_rendered.format);
|
'styles/' + id, style.serving_rendered.format, null, options);
|
||||||
style.xyz_link = tiles[0];
|
style.xyz_link = tiles[0];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -327,9 +333,9 @@ function start(opts) {
|
||||||
'/data/' + id + '.json' + query) + '/wmts';
|
'/data/' + id + '.json' + query) + '/wmts';
|
||||||
|
|
||||||
var tiles = utils.getTileUrls(
|
var tiles = utils.getTileUrls(
|
||||||
req, data_.tiles, 'data/' + id, data_.format, {
|
req, data_.tiles, 'data/' + id, data_.format, {
|
||||||
'pbf': options.pbfAlias
|
'pbf': options.pbfAlias
|
||||||
});
|
}, options);
|
||||||
data_.xyz_link = tiles[0];
|
data_.xyz_link = tiles[0];
|
||||||
}
|
}
|
||||||
if (data_.filesize) {
|
if (data_.filesize) {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ var path = require('path'),
|
||||||
var clone = require('clone'),
|
var clone = require('clone'),
|
||||||
glyphCompose = require('glyph-pbf-composite');
|
glyphCompose = require('glyph-pbf-composite');
|
||||||
|
|
||||||
module.exports.getTileUrls = function(req, domains, path, format, aliases) {
|
module.exports.getTileUrls = function(req, domains, path, format, aliases, options) {
|
||||||
|
|
||||||
if (domains) {
|
if (domains) {
|
||||||
if (domains.constructor === String && domains.length > 0) {
|
if (domains.constructor === String && domains.length > 0) {
|
||||||
|
|
@ -36,8 +36,8 @@ module.exports.getTileUrls = function(req, domains, path, format, aliases) {
|
||||||
|
|
||||||
var key = req.query.key;
|
var key = req.query.key;
|
||||||
var queryParams = [];
|
var queryParams = [];
|
||||||
if (req.query.key) {
|
if (req.query[options.auth.keyName]) {
|
||||||
queryParams.push('key=' + req.query.key);
|
queryParams.push(options.auth.keyName + '=' + req.query[options.auth.keyName]);
|
||||||
}
|
}
|
||||||
if (req.query.style) {
|
if (req.query.style) {
|
||||||
queryParams.push('style=' + req.query.style);
|
queryParams.push('style=' + req.query.style);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue