diff --git a/src/app.js b/src/serve_raster.js similarity index 98% rename from src/app.js rename to src/serve_raster.js index f7004a1..7e84e05 100644 --- a/src/app.js +++ b/src/serve_raster.js @@ -37,13 +37,9 @@ module.exports = function(maps, options, prefix) { var lock = new asyncLock(); var app = express().disable('x-powered-by'), - domains = [], + domains = options.domains, tilePath = '/{z}/{x}/{y}.{format}'; - if (options.domains && options.domains.length > 0) { - domains = options.domains.split(','); - } - var rootPath = path.join(process.cwd(), options.root); var styleUrl = options.style; diff --git a/src/serve_vector.js b/src/serve_vector.js new file mode 100644 index 0000000..b068d2d --- /dev/null +++ b/src/serve_vector.js @@ -0,0 +1,101 @@ +'use strict'; + +var async = require('async'), + asyncLock = require('async-lock'), + crypto = require('crypto'), + fs = require('fs'), + path = require('path'), + util = require('util'), + zlib = require('zlib'); + +var abaculus = require('abaculus'), + clone = require('clone'), + concat = require('concat-stream'), + express = require('express'), + mercator = new (require('sphericalmercator'))(), + mbgl = require('mapbox-gl-native'), + mbtiles = require('mbtiles'), + request = require('request'); + +var utils = require('./utils'); + +module.exports = function(maps, options, prefix) { + var lock = new asyncLock(); + + var app = express().disable('x-powered-by'), + domains = options.domains, + tilePath = '/{z}/{x}/{y}.pbf'; + + var rootPath = path.join(process.cwd(), options.root); + + var mbtilesPath = options.mbtiles; + var map = { + tileJSON: {} + }; + maps[prefix] = map; + + var source = new mbtiles(path.join(rootPath, mbtilesPath), function(err) { + source.getInfo(function(err, info) { + map.tileJSON['name'] = prefix.substr(1); + + Object.assign(map.tileJSON, info); + + map.tileJSON['tilejson'] = '2.0.0'; + map.tileJSON['basename'] = prefix.substr(1); + map.tileJSON['format'] = 'pbf'; + + Object.assign(map.tileJSON, options.options || {}); + }); + }); + + var tilePattern = tilePath + .replace('{z}', ':z(\\d+)') + .replace('{x}', ':x(\\d+)') + .replace('{y}', ':y(\\d+)'); + + var getTile = function(z, x, y, callback) { + source.getTile(z, x, y, function(err, data, headers) { + if (err) { + callback(err); + } else { + var md5 = crypto.createHash('md5').update(data).digest('base64'); + headers['content-md5'] = md5; + headers['content-type'] = 'application/x-protobuf'; + headers['content-encoding'] = 'gzip'; + + callback(null, data, headers); + } + }); + }; + + app.get(tilePattern, function(req, res, next) { + var z = req.params.z | 0, + x = req.params.x | 0, + y = req.params.y | 0; + return getTile(z, x, y, function(err, data, headers) { + if (err) { + return next(err); + } + if (headers) { + res.set(headers); + } + if (data == null) { + return res.status(404).send('Not found'); + } else { + return res.status(200).send(data); + } + }, res, next); + }); + + app.get('/index.json', function(req, res, next) { + var info = clone(map.tileJSON); + + info.tiles = utils.getTileUrls(req.protocol, domains, req.headers.host, + prefix, tilePath, info.format, + req.query.key); + + return res.send(info); + }); + + return app; +}; diff --git a/src/server.js b/src/server.js index 7b47b90..ee5c3e6 100644 --- a/src/server.js +++ b/src/server.js @@ -13,7 +13,8 @@ var async = require('async'), express = require('express'), morgan = require('morgan'); -var serve = require('./app'), +var serve_raster = require('./serve_raster'), + serve_vector = require('./serve_vector'), utils = require('./utils'); module.exports = function(opts, callback) { @@ -36,7 +37,11 @@ module.exports = function(opts, callback) { app.use(prefix, cors()); } - app.use(prefix, serve(maps, config[prefix], prefix)); + if (config[prefix].style) { + app.use(prefix, serve_raster(maps, config[prefix], prefix)); + } else { + app.use(prefix, serve_vector(maps, config[prefix], prefix)); + } }); // serve index.html on the root @@ -50,16 +55,9 @@ module.exports = function(opts, callback) { queue.push(function(callback) { var info = clone(map.tileJSON); - var domains = [], - tilePath = '/{z}/{x}/{y}.{format}'; - - if (config[prefix].domains && config[prefix].domains.length > 0) { - domains = config[prefix].domains.split(','); - } - - info.tiles = utils.getTileUrls(req.protocol, domains, req.headers.host, - prefix, tilePath, info.format, - req.query.key); + info.tiles = utils.getTileUrls( + req.protocol, config[prefix].domains, req.headers.host, + prefix, '/{z}/{x}/{y}.{format}', info.format, req.query.key); callback(null, info); }); diff --git a/src/utils.js b/src/utils.js index aa86ba3..8bd347d 100644 --- a/src/utils.js +++ b/src/utils.js @@ -2,7 +2,16 @@ module.exports.getTileUrls = function( protocol, domains, host, path, tilePath, format, key) { - domains = domains && domains.length > 0 ? domains : [host]; + + if (domains) { + if (domains.constructor === String && domains.length > 0) { + domains = domains.split(','); + } + } + if (!domains || domains.length == 0) { + domains = [host]; + } + var query = (key && key.length > 0) ? ('?key=' + key) : ''; if (path == '/') { path = '';