diff --git a/src/main.js b/src/main.js index cbb8cc2f1..eb6060621 100644 --- a/src/main.js +++ b/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.'); diff --git a/src/pmtiles_adapter.js b/src/pmtiles_adapter.js index 72891e44f..af4f3846f 100644 --- a/src/pmtiles_adapter.js +++ b/src/pmtiles_adapter.js @@ -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:'; -} diff --git a/src/serve_data.js b/src/serve_data.js index 915795d2a..d33025789 100644 --- a/src/serve_data.js +++ b/src/serve_data.js @@ -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; diff --git a/src/serve_rendered.js b/src/serve_rendered.js index a50d69621..13ec7ca6b 100644 --- a/src/serve_rendered.js +++ b/src/serve_rendered.js @@ -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') { diff --git a/src/server.js b/src/server.js index 8939ad8e4..7bff8b984 100644 --- a/src/server.js +++ b/src/server.js @@ -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'); /** diff --git a/src/utils.js b/src/utils.js index 6db7d9db8..123fed698 100644 --- a/src/utils.js +++ b/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:'; +};