Support tilejson proxy for remote tile provider

This commit is contained in:
Frédéric Rodrigo 2020-04-02 16:18:38 +02:00
parent d5a079d8f4
commit 9ac43e8718
4 changed files with 110 additions and 37 deletions

View file

@ -21,6 +21,7 @@
"@mapbox/mapbox-gl-native": "5.0.2",
"@mapbox/mapbox-gl-style-spec": "13.12.0",
"@mapbox/mbtiles": "0.11.0",
"@mapbox/tilejson": "1.1.0",
"@mapbox/sphericalmercator": "1.1.0",
"@mapbox/vector-tile": "1.3.1",
"advanced-pool": "0.3.3",

View file

@ -7,6 +7,7 @@ const zlib = require('zlib');
const clone = require('clone');
const express = require('express');
const MBTiles = require('@mapbox/mbtiles');
const TileJSON = require('@mapbox/tilejson');
const Pbf = require('pbf');
const VectorTile = require('@mapbox/vector-tile').VectorTile;
@ -108,57 +109,95 @@ module.exports = {
return res.sendStatus(404);
}
const info = clone(item.tileJSON);
info.tiles = utils.getTileUrls(req, info.tiles,
`data/${req.params.id}`, info.format, item.publicUrl, {
'pbf': options.pbfAlias
});
if (!info.tiles || !info.tiles[0].startsWith('http')) {
info.tiles = utils.getTileUrls(req, info.tiles,
`data/${req.params.id}`, info.format, item.publicUrl, {
'pbf': options.pbfAlias
});
}
return res.send(info);
});
return app;
},
add: (options, repo, params, id, publicUrl) => {
const mbtilesFile = path.resolve(options.paths.mbtiles, params.mbtiles);
let tileJSON = {
'tiles': params.domains || options.domains
};
const mbtilesFileStats = fs.statSync(mbtilesFile);
if (!mbtilesFileStats.isFile() || mbtilesFileStats.size === 0) {
throw Error(`Not valid MBTiles file: ${mbtilesFile}`);
}
let sourceInfoPromise;
let tileJSON = {};
let source;
const sourceInfoPromise = new Promise((resolve, reject) => {
source = new MBTiles(mbtilesFile, err => {
if (err) {
reject(err);
return;
}
source.getInfo((err, info) => {
if (params.remote_tilejson) {
sourceInfoPromise = new Promise((resolve, reject) => {
source = new TileJSON(params.remote_tilejson, (err, _) => {
if (err) {
reject(err);
return;
}
tileJSON['name'] = id;
tileJSON['format'] = 'pbf';
source.getInfo((err, info) => {
if (err) {
reject(err);
return;
}
tileJSON['name'] = id;
Object.assign(tileJSON, info);
Object.assign(tileJSON, info);
tileJSON['tilejson'] = '2.0.0';
delete tileJSON['filesize'];
delete tileJSON['mtime'];
delete tileJSON['scheme'];
delete tileJSON['mtime'];
delete tileJSON['scheme'];
Object.assign(tileJSON, params.tilejson || {});
utils.fixTileJSONCenter(tileJSON);
Object.assign(tileJSON, params.tilejson || {});
utils.fixTileJSONCenter(tileJSON);
if (options.dataDecoratorFunc) {
tileJSON = options.dataDecoratorFunc(id, 'tilejson', tileJSON);
}
resolve();
if (options.dataDecoratorFunc) {
tileJSON = options.dataDecoratorFunc(id, 'tilejson', tileJSON);
}
resolve();
});
});
});
});
} else {
const mbtilesFile = path.resolve(options.paths.mbtiles, params.mbtiles);
tileJSON = {
'tiles': params.domains || options.domains
};
const mbtilesFileStats = fs.statSync(mbtilesFile);
if (!mbtilesFileStats.isFile() || mbtilesFileStats.size === 0) {
throw Error(`Not valid MBTiles file: ${mbtilesFile}`);
}
sourceInfoPromise = new Promise((resolve, reject) => {
source = new MBTiles(mbtilesFile, err => {
if (err) {
reject(err);
return;
}
source.getInfo((err, info) => {
if (err) {
reject(err);
return;
}
tileJSON['name'] = id;
tileJSON['format'] = 'pbf';
Object.assign(tileJSON, info);
tileJSON['tilejson'] = '2.0.0';
delete tileJSON['filesize'];
delete tileJSON['mtime'];
delete tileJSON['scheme'];
Object.assign(tileJSON, params.tilejson || {});
utils.fixTileJSONCenter(tileJSON);
if (options.dataDecoratorFunc) {
tileJSON = options.dataDecoratorFunc(id, 'tilejson', tileJSON);
}
resolve();
});
});
});
}
return sourceInfoPromise.then(() => {
repo[id] = {

View file

@ -19,6 +19,7 @@ const express = require('express');
const mercator = new (require('@mapbox/sphericalmercator'))();
const mbgl = require('@mapbox/mapbox-gl-native');
const MBTiles = require('@mapbox/mbtiles');
const TileJSON = require('@mapbox/tilejson');
const proj4 = require('proj4');
const request = require('request');
@ -758,6 +759,38 @@ module.exports = {
}
}
if (mbtilesFile.startsWith('http')) {
queue.push(new Promise((resolve, reject) => {
map.sources[name] = new TileJSON(mbtilesFile, (err, _) => {
map.sources[name].getInfo((err, info) => {
if (err) {
console.error(err);
return;
}
const type = source.type;
Object.assign(source, info);
source.type = type;
source.url = mbtilesFile;
if (options.dataDecoratorFunc) {
source = options.dataDecoratorFunc(name, 'tilejson', source);
}
if (!attributionOverride &&
source.attribution && source.attribution.length > 0) {
if (tileJSON.attribution.length > 0) {
tileJSON.attribution += '; ';
}
tileJSON.attribution += source.attribution;
}
resolve();
});
});
}));
continue;
}
queue.push(new Promise((resolve, reject) => {
mbtilesFile = path.resolve(options.paths.mbtiles, mbtilesFile);
const mbtilesFileStats = fs.statSync(mbtilesFile);

View file

@ -160,7 +160,7 @@ function start(opts) {
let mbtilesFile;
for (const id of Object.keys(data)) {
if (id === mbtiles) {
mbtilesFile = data[id].mbtiles;
mbtilesFile = data[id].mbtiles || data[id].remote_tilejson;
}
}
return mbtilesFile;
@ -190,8 +190,8 @@ function start(opts) {
for (const id of Object.keys(data)) {
const item = data[id];
if (!item.mbtiles || item.mbtiles.length === 0) {
console.log(`Missing "mbtiles" property for ${id}`);
if ((!item.mbtiles || item.mbtiles.length === 0) && (!item.remote_tilejson || item.remote_tilejson.length === 0)) {
console.log(`Missing "mbtiles" or "remote_tilejson" property for ${id}`);
continue;
}