we are using `cors` middleware with default options which works for most applications, but does not allow for fine tuning (whitelisting origins etc.) this change keeps CORS handling as default to preserve compatibility but also allows for specying `--no-cors` option which makes it possible to handle CORS in an independent proxy (NGINX, another node app etc.)
208 lines
6.0 KiB
JavaScript
208 lines
6.0 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
'use strict';
|
|
|
|
var fs = require('fs'),
|
|
path = require('path'),
|
|
request = require('request');
|
|
|
|
var mbtiles = require('mbtiles');
|
|
|
|
var packageJson = require('../package');
|
|
|
|
var opts = require('nomnom')
|
|
.option('mbtiles', {
|
|
default: undefined,
|
|
help: 'MBTiles file (uses demo configuration);\n' +
|
|
'\t ignored if the configuration file is also specified',
|
|
position: 0
|
|
})
|
|
.option('config', {
|
|
abbr: 'c',
|
|
default: 'config.json',
|
|
help: 'Configuration file'
|
|
})
|
|
.option('bind', {
|
|
abbr: 'b',
|
|
default: undefined,
|
|
help: 'Bind address'
|
|
})
|
|
.option('port', {
|
|
abbr: 'p',
|
|
default: 8080,
|
|
help: 'Port'
|
|
})
|
|
.option('cors', {
|
|
default: true,
|
|
help: 'Enable Cross-origin resource sharing headers'
|
|
})
|
|
.option('verbose', {
|
|
abbr: 'V',
|
|
flag: true,
|
|
help: 'More verbose output'
|
|
})
|
|
.option('version', {
|
|
abbr: 'v',
|
|
flag: true,
|
|
help: 'Version info',
|
|
callback: function() {
|
|
return packageJson.name + ' v' + packageJson.version;
|
|
}
|
|
}).parse();
|
|
|
|
|
|
console.log('Starting ' + packageJson.name + ' v' + packageJson.version);
|
|
|
|
var startServer = function(configPath, config) {
|
|
return require('./server')({
|
|
configPath: configPath,
|
|
config: config,
|
|
bind: opts.bind,
|
|
port: opts.port,
|
|
cors: opts.cors
|
|
});
|
|
};
|
|
|
|
var startWithMBTiles = function(mbtilesFile) {
|
|
console.log('Automatically creating config file for ' + mbtilesFile);
|
|
|
|
mbtilesFile = path.resolve(process.cwd(), mbtilesFile);
|
|
|
|
var mbtilesStats = fs.statSync(mbtilesFile);
|
|
if (!mbtilesStats.isFile() || mbtilesStats.size === 0) {
|
|
console.log('ERROR: Not valid MBTiles file: ' + mbtilesFile);
|
|
process.exit(1);
|
|
}
|
|
var instance = new mbtiles(mbtilesFile, function(err) {
|
|
instance.getInfo(function(err, info) {
|
|
if (err || !info) {
|
|
console.log('ERROR: Metadata missing in the MBTiles.');
|
|
console.log(' Make sure ' + path.basename(mbtilesFile) +
|
|
' is valid MBTiles.');
|
|
process.exit(1);
|
|
}
|
|
var bounds = info.bounds;
|
|
|
|
var styleDir = path.resolve(__dirname, "../node_modules/tileserver-gl-styles/");
|
|
|
|
var config = {
|
|
"options": {
|
|
"paths": {
|
|
"root": styleDir,
|
|
"fonts": "fonts",
|
|
"styles": "styles",
|
|
"mbtiles": path.dirname(mbtilesFile)
|
|
}
|
|
},
|
|
"styles": {},
|
|
"data": {}
|
|
};
|
|
|
|
if (info.format == 'pbf' &&
|
|
info.name.toLowerCase().indexOf('openmaptiles') > -1) {
|
|
var omtV = (info.version || '').split('.');
|
|
|
|
config['data']['v' + omtV[0]] = {
|
|
"mbtiles": path.basename(mbtilesFile)
|
|
};
|
|
|
|
|
|
var styles = fs.readdirSync(path.resolve(styleDir, 'styles'));
|
|
for (var i = 0; i < styles.length; i++) {
|
|
var styleName = styles[i];
|
|
var styleFileRel = styleName + '/style.json';
|
|
var styleFile = path.resolve(styleDir, 'styles', styleFileRel);
|
|
if (fs.existsSync(styleFile)) {
|
|
var styleJSON = require(styleFile);
|
|
var omtVersionCompatibility =
|
|
((styleJSON || {}).metadata || {})['openmaptiles:version'] || 'x';
|
|
var m = omtVersionCompatibility.toLowerCase().split('.');
|
|
|
|
var isCompatible = !(
|
|
m[0] != 'x' && (
|
|
m[0] != omtV[0] || (
|
|
(m[1] || 'x') != 'x' && (
|
|
m[1] != omtV[1] || (
|
|
(m[2] || 'x') != 'x' &&
|
|
m[2] != omtV[2]
|
|
)
|
|
)
|
|
)
|
|
)
|
|
);
|
|
|
|
if (isCompatible) {
|
|
var styleObject = {
|
|
"style": styleFileRel,
|
|
"tilejson": {
|
|
"bounds": bounds
|
|
}
|
|
};
|
|
config['styles'][styleName] = styleObject;
|
|
} else {
|
|
console.log('Style', styleName, 'requires OpenMapTiles version',
|
|
omtVersionCompatibility, 'but mbtiles is version', info.version);
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
console.log('WARN: MBTiles not in "openmaptiles" format. ' +
|
|
'Serving raw data only...');
|
|
config['data'][(info.id || 'mbtiles')
|
|
.replace(/\//g, '_')
|
|
.replace(/\:/g, '_')
|
|
.replace(/\?/g, '_')] = {
|
|
"mbtiles": path.basename(mbtilesFile)
|
|
};
|
|
}
|
|
|
|
if (opts.verbose) {
|
|
console.log(JSON.stringify(config, undefined, 2));
|
|
} else {
|
|
console.log('Run with --verbose to see the config file here.');
|
|
}
|
|
|
|
return startServer(null, config);
|
|
});
|
|
});
|
|
};
|
|
|
|
fs.stat(path.resolve(opts.config), function(err, stats) {
|
|
if (err || !stats.isFile() || stats.size === 0) {
|
|
var mbtiles = opts.mbtiles;
|
|
if (!mbtiles) {
|
|
// try to find in the cwd
|
|
var files = fs.readdirSync(process.cwd());
|
|
for (var i=0; i < files.length; i++) {
|
|
var filename = files[i];
|
|
if (filename.endsWith('.mbtiles')) {
|
|
var mbTilesStats = fs.statSync(filename);
|
|
if (mbTilesStats.isFile() && mbTilesStats.size > 0) {
|
|
mbtiles = filename;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (mbtiles) {
|
|
console.log('No MBTiles specified, using ' + mbtiles);
|
|
return startWithMBTiles(mbtiles);
|
|
} else {
|
|
var url = 'https://github.com/klokantech/tileserver-gl/releases/download/v1.3.0/zurich_switzerland.mbtiles';
|
|
var filename = 'zurich_switzerland.mbtiles';
|
|
var stream = fs.createWriteStream(filename);
|
|
console.log('Downloading sample data (' + filename + ') from ' + url);
|
|
stream.on('finish', function() {
|
|
return startWithMBTiles(filename);
|
|
});
|
|
return request.get(url).pipe(stream);
|
|
}
|
|
}
|
|
if (mbtiles) {
|
|
return startWithMBTiles(mbtiles);
|
|
}
|
|
} else {
|
|
console.log('Using specified config file from ' + opts.config);
|
|
return startServer(opts.config, null);
|
|
}
|
|
});
|