feat: allow web https based pmtiles to be loaded
Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
This commit is contained in:
parent
3f45c38663
commit
fde9ed96a5
6 changed files with 80 additions and 39 deletions
49
src/main.js
49
src/main.js
|
|
@ -8,6 +8,7 @@ import { fileURLToPath } from 'url';
|
|||
import request from 'request';
|
||||
import { server } from './server.js';
|
||||
import MBTiles from '@mapbox/mbtiles';
|
||||
import { isValidHttpUrl } from './utils.js';
|
||||
import {
|
||||
PMtilesOpen,
|
||||
PMtilesClose,
|
||||
|
|
@ -91,12 +92,18 @@ const startWithinputFile = async (inputFile) => {
|
|||
`[INFO] See documentation to learn how to create config.json file.`,
|
||||
);
|
||||
|
||||
inputFile = path.resolve(process.cwd(), inputFile);
|
||||
let inputFilePath;
|
||||
if (isValidHttpUrl(inputFile)) {
|
||||
inputFilePath = process.cwd();
|
||||
} else {
|
||||
inputFile = path.resolve(process.cwd(), inputFile);
|
||||
inputFilePath = path.dirname(inputFile);
|
||||
|
||||
const inputFileStats = fs.statSync(inputFile);
|
||||
if (!inputFileStats.isFile() || inputFileStats.size === 0) {
|
||||
console.log(`ERROR: Not a valid input file: ${inputFile}`);
|
||||
process.exit(1);
|
||||
const inputFileStats = fs.statSync(inputFile);
|
||||
if (!inputFileStats.isFile() || inputFileStats.size === 0) {
|
||||
console.log(`ERROR: Not a valid input file: `);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const styleDir = path.resolve(
|
||||
|
|
@ -110,8 +117,8 @@ const startWithinputFile = async (inputFile) => {
|
|||
root: styleDir,
|
||||
fonts: 'fonts',
|
||||
styles: 'styles',
|
||||
mbtiles: path.dirname(inputFile),
|
||||
pmtiles: path.dirname(inputFile),
|
||||
mbtiles: inputFilePath,
|
||||
pmtiles: inputFilePath,
|
||||
},
|
||||
},
|
||||
styles: {},
|
||||
|
|
@ -132,9 +139,15 @@ const startWithinputFile = async (inputFile) => {
|
|||
metadata.format === 'pbf' &&
|
||||
metadata.name.toLowerCase().indexOf('openmaptiles') > -1
|
||||
) {
|
||||
config['data'][`v3`] = {
|
||||
pmtiles: path.basename(inputFile),
|
||||
};
|
||||
if (isValidHttpUrl(inputFile)) {
|
||||
config['data'][`v3`] = {
|
||||
pmtiles: inputFile,
|
||||
};
|
||||
} else {
|
||||
config['data'][`v3`] = {
|
||||
pmtiles: path.basename(inputFile),
|
||||
};
|
||||
}
|
||||
|
||||
const styles = fs.readdirSync(path.resolve(styleDir, 'styles'));
|
||||
for (const styleName of styles) {
|
||||
|
|
@ -153,9 +166,15 @@ const startWithinputFile = async (inputFile) => {
|
|||
console.log(
|
||||
`WARN: PMTiles not in "openmaptiles" format. Serving raw data only...`,
|
||||
);
|
||||
config['data'][(metadata.id || 'pmtiles').replace(/[?/:]/g, '_')] = {
|
||||
pmtiles: path.basename(inputFile),
|
||||
};
|
||||
if (isValidHttpUrl(inputFile)) {
|
||||
config['data'][(metadata.id || 'pmtiles').replace(/[?/:]/g, '_')] = {
|
||||
pmtiles: inputFile,
|
||||
};
|
||||
} else {
|
||||
config['data'][(metadata.id || 'pmtiles').replace(/[?/:]/g, '_')] = {
|
||||
pmtiles: path.basename(inputFile),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.verbose) {
|
||||
|
|
@ -166,6 +185,10 @@ const startWithinputFile = async (inputFile) => {
|
|||
|
||||
return startServer(null, config);
|
||||
} else {
|
||||
if (isValidHttpUrl(inputFile)) {
|
||||
console.log(`ERROR: MBTiles does not support web based files: `);
|
||||
process.exit(1);
|
||||
}
|
||||
const instance = new MBTiles(inputFile + '?mode=ro', (err) => {
|
||||
if (err) {
|
||||
console.log('ERROR: Unable to open MBTiles.');
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import fs from 'node:fs';
|
||||
import PMTiles from 'pmtiles';
|
||||
import { isValidHttpUrl } from './utils.js';
|
||||
|
||||
const PMTilesFileSource = class {
|
||||
constructor(fd) {
|
||||
|
|
@ -122,19 +123,3 @@ const ArrayBufferToBuffer = (array_buffer) => {
|
|||
}
|
||||
return buffer;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string
|
||||
*/
|
||||
function isValidHttpUrl(string) {
|
||||
let url;
|
||||
|
||||
try {
|
||||
url = new URL(string);
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return url.protocol === 'http:' || url.protocol === 'https:';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import MBTiles from '@mapbox/mbtiles';
|
|||
import Pbf from 'pbf';
|
||||
import { VectorTile } from '@mapbox/vector-tile';
|
||||
|
||||
import { getTileUrls, fixTileJSONCenter } from './utils.js';
|
||||
import { getTileUrls, isValidHttpUrl, fixTileJSONCenter } from './utils.js';
|
||||
import {
|
||||
PMtilesOpen,
|
||||
GetPMtilesInfo,
|
||||
|
|
@ -194,20 +194,32 @@ export const serve_data = {
|
|||
let inputFile;
|
||||
let inputType;
|
||||
if (params.pmtiles) {
|
||||
inputFile = path.resolve(options.paths.pmtiles, params.pmtiles);
|
||||
inputType = 'pmtiles';
|
||||
if (isValidHttpUrl(params.pmtiles)) {
|
||||
inputFile = params.pmtiles;
|
||||
} else {
|
||||
inputFile = path.resolve(options.paths.pmtiles, params.pmtiles);
|
||||
}
|
||||
} else if (params.mbtiles) {
|
||||
inputFile = path.resolve(options.paths.mbtiles, params.mbtiles);
|
||||
inputType = 'mbtiles';
|
||||
if (isValidHttpUrl(params.pmtiles)) {
|
||||
throw Error(
|
||||
`ERROR: MBTiles does not support web based files: ${inputFile}`,
|
||||
);
|
||||
} else {
|
||||
inputFile = path.resolve(options.paths.mbtiles, params.mbtiles);
|
||||
}
|
||||
}
|
||||
|
||||
let tileJSON = {
|
||||
tiles: params.domains || options.domains,
|
||||
};
|
||||
|
||||
const inputFileStats = fs.statSync(inputFile);
|
||||
if (!inputFileStats.isFile() || inputFileStats.size === 0) {
|
||||
throw Error(`Not valid input file: ${inputFile}`);
|
||||
if (!isValidHttpUrl(inputFile)) {
|
||||
const inputFileStats = fs.statSync(inputFile);
|
||||
if (!inputFileStats.isFile() || inputFileStats.size === 0) {
|
||||
throw Error(`Not valid input file: ${inputFile}`);
|
||||
}
|
||||
}
|
||||
|
||||
let source;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,12 @@ import MBTiles from '@mapbox/mbtiles';
|
|||
import polyline from '@mapbox/polyline';
|
||||
import proj4 from 'proj4';
|
||||
import request from 'request';
|
||||
import { getFontsPbf, getTileUrls, fixTileJSONCenter } from './utils.js';
|
||||
import {
|
||||
getFontsPbf,
|
||||
getTileUrls,
|
||||
isValidHttpUrl,
|
||||
fixTileJSONCenter,
|
||||
} from './utils.js';
|
||||
import {
|
||||
PMtilesOpen,
|
||||
GetPMtilesInfo,
|
||||
|
|
@ -1489,9 +1494,11 @@ export const serve_rendered = {
|
|||
}
|
||||
}
|
||||
|
||||
const inputFileStats = fs.statSync(inputFile);
|
||||
if (!inputFileStats.isFile() || inputFileStats.size === 0) {
|
||||
throw Error(`Not valid MBTiles file: ${inputFile}`);
|
||||
if (!isValidHttpUrl(inputFile)) {
|
||||
const inputFileStats = fs.statSync(inputFile);
|
||||
if (!inputFileStats.isFile() || inputFileStats.size === 0) {
|
||||
throw Error(`Not valid PMTiles file: ${inputFile}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (source_type === 'pmtiles') {
|
||||
|
|
|
|||
|
|
@ -93,6 +93,7 @@ function start(opts) {
|
|||
paths.fonts = path.resolve(paths.root, paths.fonts || '');
|
||||
paths.sprites = path.resolve(paths.root, paths.sprites || '');
|
||||
paths.mbtiles = path.resolve(paths.root, paths.mbtiles || '');
|
||||
paths.pmtiles = path.resolve(paths.root, paths.pmtiles || '');
|
||||
paths.icons = path.resolve(paths.root, paths.icons || '');
|
||||
|
||||
const startupPromises = [];
|
||||
|
|
@ -109,6 +110,7 @@ function start(opts) {
|
|||
checkPath('fonts');
|
||||
checkPath('sprites');
|
||||
checkPath('mbtiles');
|
||||
checkPath('pmtiles');
|
||||
checkPath('icons');
|
||||
|
||||
/**
|
||||
|
|
|
|||
12
src/utils.js
12
src/utils.js
|
|
@ -162,3 +162,15 @@ export const getFontsPbf = (
|
|||
|
||||
return Promise.all(queue).then((values) => glyphCompose.combine(values));
|
||||
};
|
||||
|
||||
export const isValidHttpUrl = (string) => {
|
||||
let url;
|
||||
|
||||
try {
|
||||
url = new URL(string);
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return url.protocol === 'http:' || url.protocol === 'https:';
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue