Skip to content

Commit

Permalink
feat: allow web https based pmtiles to be loaded
Browse files Browse the repository at this point in the history
Signed-off-by: Andrew Calcutt <[email protected]>
  • Loading branch information
acalcutt committed Oct 11, 2023
1 parent 3f45c38 commit fde9ed9
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 39 deletions.
49 changes: 36 additions & 13 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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(
Expand All @@ -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: {},
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -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.');
Expand Down
17 changes: 1 addition & 16 deletions src/pmtiles_adapter.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import fs from 'node:fs';
import PMTiles from 'pmtiles';
import { isValidHttpUrl } from './utils.js';

const PMTilesFileSource = class {
constructor(fd) {
Expand Down Expand Up @@ -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:';
}
24 changes: 18 additions & 6 deletions src/serve_data.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down
15 changes: 11 additions & 4 deletions src/serve_rendered.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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') {
Expand Down
2 changes: 2 additions & 0 deletions src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [];
Expand All @@ -109,6 +110,7 @@ function start(opts) {
checkPath('fonts');
checkPath('sprites');
checkPath('mbtiles');
checkPath('pmtiles');
checkPath('icons');

/**
Expand Down
12 changes: 12 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -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:';
};

0 comments on commit fde9ed9

Please sign in to comment.