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-native": "5.0.2",
"@mapbox/mapbox-gl-style-spec": "13.12.0", "@mapbox/mapbox-gl-style-spec": "13.12.0",
"@mapbox/mbtiles": "0.11.0", "@mapbox/mbtiles": "0.11.0",
"@mapbox/tilejson": "1.1.0",
"@mapbox/sphericalmercator": "1.1.0", "@mapbox/sphericalmercator": "1.1.0",
"@mapbox/vector-tile": "1.3.1", "@mapbox/vector-tile": "1.3.1",
"advanced-pool": "0.3.3", "advanced-pool": "0.3.3",

View file

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

View file

@ -19,6 +19,7 @@ const express = require('express');
const mercator = new (require('@mapbox/sphericalmercator'))(); const mercator = new (require('@mapbox/sphericalmercator'))();
const mbgl = require('@mapbox/mapbox-gl-native'); const mbgl = require('@mapbox/mapbox-gl-native');
const MBTiles = require('@mapbox/mbtiles'); const MBTiles = require('@mapbox/mbtiles');
const TileJSON = require('@mapbox/tilejson');
const proj4 = require('proj4'); const proj4 = require('proj4');
const request = require('request'); 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) => { queue.push(new Promise((resolve, reject) => {
mbtilesFile = path.resolve(options.paths.mbtiles, mbtilesFile); mbtilesFile = path.resolve(options.paths.mbtiles, mbtilesFile);
const mbtilesFileStats = fs.statSync(mbtilesFile); const mbtilesFileStats = fs.statSync(mbtilesFile);

View file

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