Compare commits

..

18 Commits
v0.6 ... v0.8.2

Author SHA1 Message Date
Petr Sloup
5a20bf4fac Update version to 0.8.2 2016-07-26 18:57:39 +07:00
Petr Sloup
a0fbf7fb79 Fix font compositing (close #32) 2016-07-26 18:56:32 +07:00
Petr Sloup
ed0af943da New design (close #31) 2016-07-26 17:27:08 +07:00
Petr Sloup
e4ce4877b6 Update version to 0.8.1 2016-07-26 10:43:33 +08:00
Petr Sloup
a0a086e95a Update dependencies 2016-07-26 10:43:33 +08:00
Petr Sloup
dbaca66b2c Add `Last-Modified' headers to improve caching 2016-07-26 10:43:33 +08:00
Petr Sloup
d465142275 Merge pull request #28 from stirringhalo/master
Avoid curl | bash
2016-07-22 19:02:22 +08:00
stirringhalo
7f06f09696 Duplicate nodejs install 2016-07-20 15:18:58 -04:00
stirringhalo
f5c5570fca Avoid curl | bash 2016-07-18 18:42:09 -04:00
Petr Sloup
cb10936a1d Update version to 0.8.0 2016-07-13 14:06:58 +02:00
Petr Sloup
a43c96f6cc Print package version to log and index 2016-07-13 14:04:42 +02:00
Petr Sloup
a310c130f3 Download sample data when running docker image without config (close #23) 2016-07-13 14:03:41 +02:00
Petr Sloup
14f406cc34 Add "bin" entry to package.json 2016-07-13 13:08:48 +02:00
Petr Sloup
3c29cb0f65 ETag/caching fixes and improvements 2016-07-13 12:56:59 +02:00
Petr Sloup
d993c805fe Update dependencies 2016-07-13 12:56:41 +02:00
Petr Sloup
6443ade489 Update version to 0.7.0 2016-06-30 12:25:03 +02:00
Petr Sloup
eeb27ed481 Downgrade mapbox-gl-js to v0.16.0
To fix rendering issues with certain datasets on older devices
2016-06-30 12:22:46 +02:00
Petr Sloup
15bc393aa8 Use URl-safe base64 alphabet 2016-06-30 12:19:32 +02:00
23 changed files with 482 additions and 376 deletions

View File

@@ -3,13 +3,19 @@ MAINTAINER Petr Sloup <petr.sloup@klokantech.com>
RUN apt-get -qq update \ RUN apt-get -qq update \
&& DEBIAN_FRONTEND=noninteractive apt-get -y install \ && DEBIAN_FRONTEND=noninteractive apt-get -y install \
apt-transport-https \
curl \ curl \
unzip \
build-essential \ build-essential \
python \ python \
libcairo2-dev \ libcairo2-dev \
xvfb \ xvfb \
&& curl -sL https://deb.nodesource.com/setup_4.x | bash - \ && echo "deb https://deb.nodesource.com/node_4.x jessie main" >> /etc/apt/sources.list.d/nodejs.list \
&& apt-get -y install nodejs \ && echo "deb-src https://deb.nodesource.com/node_4.x jessie main" >> /etc/apt/sources.list.d/nodejs.list \
&& apt-get -qq update \
&& DEBIAN_FRONTEND=noninteractive apt-get -y --allow-unauthenticated install \
nodejs \
&& rm /etc/apt/sources.list.d/nodejs.list \
&& apt-get clean && apt-get clean
RUN mkdir -p /usr/src/app RUN mkdir -p /usr/src/app

View File

@@ -1,8 +1,9 @@
{ {
"name": "tileserver-gl", "name": "tileserver-gl",
"version": "0.6.0", "version": "0.8.2",
"description": "Map tile server for JSON GL styles - serverside generated raster tiles", "description": "Map tile server for JSON GL styles - serverside generated raster tiles",
"main": "src/main.js", "main": "src/main.js",
"bin": "src/main.js",
"authors": [ "authors": [
"Petr Sloup <petr.sloup@klokantech.com>" "Petr Sloup <petr.sloup@klokantech.com>"
], ],
@@ -15,24 +16,26 @@
"test": "mocha test/**.js" "test": "mocha test/**.js"
}, },
"dependencies": { "dependencies": {
"async": "1.5.2", "async": "2.0.1",
"advanced-pool": "0.3.2", "advanced-pool": "0.3.2",
"base64url": "2.0.0",
"canvas": "1.4.0", "canvas": "1.4.0",
"clone": "1.0.2", "clone": "1.0.2",
"color": "0.11.3", "color": "0.11.3",
"cors": "2.7.1", "cors": "2.7.1",
"express": "4.14.0", "express": "4.14.0",
"glyph-pbf-composite": "0.0.2",
"handlebars": "4.0.5", "handlebars": "4.0.5",
"mapbox-gl-native": "3.2.1", "mapbox-gl-native": "3.2.1",
"mbtiles": "0.9.0", "mbtiles": "0.9.0",
"morgan": "1.7.0", "morgan": "1.7.0",
"nomnom": "1.8.1", "nomnom": "1.8.1",
"request": "2.72.0", "request": "2.74.0",
"sharp": "0.15.0", "sharp": "0.15.1",
"sphericalmercator": "1.0.5" "sphericalmercator": "1.0.5"
}, },
"devDependencies": { "devDependencies": {
"should": "^9.0.0", "should": "^10.0.0",
"mocha": "^2.5.0", "mocha": "^2.5.0",
"supertest": "^1.2.0" "supertest": "^1.2.0"
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

9
run.sh
View File

@@ -1,2 +1,11 @@
#!/bin/bash #!/bin/bash
if [ ! -f /data/config.json ]; then
echo "INFO: No config.json found! Downloading sample data..."
echo "--------------------------------------------------------------------------------"
curl -L -o sample_data.zip https://github.com/klokantech/tileserver-gl-data/archive/v0.8.0.zip
unzip -q sample_data.zip -d sample_data
mv sample_data/tileserver-gl-data-*/* -t /data
rm sample_data.zip
rm -r sample_data
fi
xvfb-run -a -e /dev/stdout --server-args="-screen 0 1024x768x24" node /usr/src/app/src/main.js -p 80 -c /data/config.json xvfb-run -a -e /dev/stdout --server-args="-screen 0 1024x768x24" node /usr/src/app/src/main.js -p 80 -c /data/config.json

View File

@@ -1,7 +1,6 @@
'use strict'; 'use strict';
var crypto = require('crypto'), var fs = require('fs'),
fs = require('fs'),
path = require('path'); path = require('path');
var clone = require('clone'), var clone = require('clone'),
@@ -59,12 +58,11 @@ module.exports = function(options, repo, params, id) {
return res.status(500).send(err.message); return res.status(500).send(err.message);
} }
} else { } else {
var md5 = crypto.createHash('md5').update(data).digest('base64');
headers['content-md5'] = md5;
if (tileJSON['format'] == 'pbf') { if (tileJSON['format'] == 'pbf') {
headers['content-type'] = 'application/x-protobuf'; headers['Content-Type'] = 'application/x-protobuf';
headers['content-encoding'] = 'gzip'; headers['Content-Encoding'] = 'gzip';
} }
delete headers['ETag']; // do not trust the tile ETag -- regenerate
res.set(headers); res.set(headers);
if (data == null) { if (data == null) {

View File

@@ -1,56 +1,29 @@
'use strict'; 'use strict';
var async = require('async'),
path = require('path'),
fs = require('fs');
var clone = require('clone'), var clone = require('clone'),
express = require('express'); express = require('express');
var utils = require('./utils');
module.exports = function(options, allowedFonts) { module.exports = function(options, allowedFonts) {
var app = express().disable('x-powered-by'); var app = express().disable('x-powered-by');
var fontPath = options.paths.fonts; var lastModified = new Date().toUTCString();
var getFontPbf = function(name, range, callback) { var fontPath = options.paths.fonts;
// if some of the files failed to load (does not exist or not allowed),
// return empty buffer so the other fonts can still work
if (allowedFonts[name]) {
var filename = path.join(fontPath, name, range + '.pbf');
return fs.readFile(filename, function(err, data) {
if (err) {
console.log('Font load error:', filename);
return callback(null, new Buffer([]));
} else {
return callback(null, data);
}
});
} else {
return callback(null, new Buffer([]));
}
};
app.get('/:fontstack/:range([\\d]+-[\\d]+).pbf', app.get('/:fontstack/:range([\\d]+-[\\d]+).pbf',
function(req, res, next) { function(req, res, next) {
var fontstack = decodeURI(req.params.fontstack); var fontstack = decodeURI(req.params.fontstack);
var range = req.params.range; var range = req.params.range;
var fonts = fontstack.split(','); return utils.getFontsPbf(allowedFonts, fontPath, fontstack, range,
function(err, concated) {
var queue = []; if (err || concated.length === 0) {
fonts.forEach(function(font) {
queue.push(function(callback) {
getFontPbf(font, range, callback);
});
});
return async.parallel(queue, function(err, results) {
var concated = Buffer.concat(results);
if (err || concated.length == 0) {
return res.status(400).send(''); return res.status(400).send('');
} else { } else {
res.header('Content-type', 'application/x-protobuf'); res.header('Content-type', 'application/x-protobuf');
res.header('Last-Modified', lastModified);
return res.send(concated); return res.send(concated);
} }
}); });

View File

@@ -2,7 +2,6 @@
var async = require('async'), var async = require('async'),
advancedPool = require('advanced-pool'), advancedPool = require('advanced-pool'),
crypto = require('crypto'),
fs = require('fs'), fs = require('fs'),
path = require('path'), path = require('path'),
util = require('util'), util = require('util'),
@@ -39,6 +38,8 @@ mbgl.on('message', function(e) {
module.exports = function(options, repo, params, id) { module.exports = function(options, repo, params, id) {
var app = express().disable('x-powered-by'); var app = express().disable('x-powered-by');
var lastModified = new Date().toUTCString();
var rootPath = options.paths.root; var rootPath = options.paths.root;
var styleFile = params.style; var styleFile = params.style;
@@ -55,12 +56,20 @@ module.exports = function(options, repo, params, id) {
request: function(req, callback) { request: function(req, callback) {
var protocol = req.url.split(':')[0]; var protocol = req.url.split(':')[0];
//console.log('Handling request:', req); //console.log('Handling request:', req);
if (protocol == 'sprites' || protocol == 'fonts') { if (protocol == 'sprites') {
var dir = options.paths[protocol]; var dir = options.paths[protocol];
var file = unescape(req.url).substring(protocol.length + 3); var file = unescape(req.url).substring(protocol.length + 3);
fs.readFile(path.join(dir, file), function(err, data) { fs.readFile(path.join(dir, file), function(err, data) {
callback(err, { data: data }); callback(err, { data: data });
}); });
} else if (protocol == 'fonts') {
var parts = req.url.split('/');
var fontstack = unescape(parts[2]);
var range = parts[3].split('.')[0];
utils.getFontsPbf(null, options.paths[protocol], fontstack, range,
function(err, concated) {
callback(err, {data: concated});
});
} else if (protocol == 'mbtiles') { } else if (protocol == 'mbtiles') {
var parts = req.url.split('/'); var parts = req.url.split('/');
var source = map.sources[parts[2]]; var source = map.sources[parts[2]];
@@ -78,9 +87,6 @@ module.exports = function(options, repo, params, id) {
if (headers['Last-Modified']) { if (headers['Last-Modified']) {
response.modified = new Date(headers['Last-Modified']); response.modified = new Date(headers['Last-Modified']);
} }
if (headers['ETag']) {
response.etag = headers['ETag'];
}
if (format == 'pbf') { if (format == 'pbf') {
response.data = zlib.unzipSync(data); response.data = zlib.unzipSync(data);
@@ -292,10 +298,9 @@ module.exports = function(options, repo, params, id) {
return res.status(404).send('Not found'); return res.status(404).send('Not found');
} }
var md5 = crypto.createHash('md5').update(buffer).digest('base64');
res.set({ res.set({
'content-md5': md5, 'Last-Modified': lastModified,
'content-type': 'image/' + format 'Content-Type': 'image/' + format
}); });
return res.status(200).send(buffer); return res.status(200).send(buffer);
}); });

View File

@@ -7,20 +7,24 @@ process.env.UV_THREADPOOL_SIZE =
var fs = require('fs'), var fs = require('fs'),
path = require('path'); path = require('path');
var clone = require('clone'), var base64url = require('base64url'),
clone = require('clone'),
cors = require('cors'), cors = require('cors'),
express = require('express'), express = require('express'),
handlebars = require('handlebars'), handlebars = require('handlebars'),
mercator = new (require('sphericalmercator'))(), mercator = new (require('sphericalmercator'))(),
morgan = require('morgan'); morgan = require('morgan');
var serve_font = require('./serve_font'), var packageJson = require('../package'),
serve_font = require('./serve_font'),
serve_rendered = require('./serve_rendered'), serve_rendered = require('./serve_rendered'),
serve_style = require('./serve_style'), serve_style = require('./serve_style'),
serve_data = require('./serve_data'), serve_data = require('./serve_data'),
utils = require('./utils'); utils = require('./utils');
module.exports = function(opts, callback) { module.exports = function(opts, callback) {
console.log('Starting TileServer-GL v' + packageJson.version);
var app = express().disable('x-powered-by'), var app = express().disable('x-powered-by'),
serving = { serving = {
styles: {}, styles: {},
@@ -172,6 +176,7 @@ module.exports = function(opts, callback) {
return res.status(404).send('Not found'); return res.status(404).send('Not found');
} }
} }
data['server_version'] = packageJson.version;
data['key_query_part'] = data['key_query_part'] =
req.query.key ? 'key=' + req.query.key + '&amp;' : ''; req.query.key ? 'key=' + req.query.key + '&amp;' : '';
data['key_query'] = req.query.key ? '?key=' + req.query.key : ''; data['key_query'] = req.query.key ? '?key=' + req.query.key : '';
@@ -201,10 +206,9 @@ module.exports = function(opts, callback) {
} }
var query = req.query.key ? ('?key=' + req.query.key) : ''; var query = req.query.key ? ('?key=' + req.query.key) : '';
style.wmts_link = 'https://wmts.maptiler.com/' + style.wmts_link = 'http://wmts.maptiler.com/' +
new Buffer(req.protocol + '://' + req.headers.host + base64url('http://' + req.headers.host +
'/styles/' + id + '/rendered.json' + query).toString('base64') + '/styles/' + id + '/rendered.json' + query) + '/wmts';
'/wmts';
} }
}); });
var data = clone(serving.data || {}); var data = clone(serving.data || {});
@@ -227,8 +231,8 @@ module.exports = function(opts, callback) {
var query = req.query.key ? ('?key=' + req.query.key) : ''; var query = req.query.key ? ('?key=' + req.query.key) : '';
data_.wmts_link = 'http://wmts.maptiler.com/' + data_.wmts_link = 'http://wmts.maptiler.com/' +
new Buffer('http://' + req.headers.host + base64url('http://' + req.headers.host +
'/data/' + id + '.json' + query).toString('base64') + '/wmts'; '/data/' + id + '.json' + query) + '/wmts';
} }
if (data_.filesize) { if (data_.filesize) {
var suffix = 'kB'; var suffix = 'kB';

View File

@@ -1,5 +1,11 @@
'use strict'; 'use strict';
var async = require('async'),
path = require('path'),
fs = require('fs');
var glyphCompose = require('glyph-pbf-composite');
module.exports.getTileUrls = function(req, domains, path, format) { module.exports.getTileUrls = function(req, domains, path, format) {
if (domains) { if (domains) {
@@ -37,3 +43,36 @@ module.exports.fixTileJSONCenter = function(tileJSON) {
]; ];
} }
}; };
module.exports.getFontsPbf = function(allowedFonts, fontPath, names, range, callback) {
var getFontPbf = function(name, range, callback) {
if (!allowedFonts || allowedFonts[name]) {
var filename = path.join(fontPath, name, range + '.pbf');
return fs.readFile(filename, function(err, data) {
if (err) {
return callback(new Error('Font load error: ' + name));
} else {
return callback(null, data);
}
});
} else {
return callback(new Error('Font not allowed: ' + name));
}
};
var fonts = names.split(',');
var queue = [];
fonts.forEach(function(font) {
queue.push(function(callback) {
getFontPbf(font, range, callback);
});
});
return async.parallel(queue, function(err, results) {
if (err) {
callback(err, new Buffer([]));
} else {
callback(err, glyphCompose.combine(results));
}
});
};

View File

@@ -42,7 +42,7 @@ describe('Fonts', function() {
testIs('/fonts/Open Sans Regular/65280-65533.pbf', /application\/x-protobuf/); testIs('/fonts/Open Sans Regular/65280-65533.pbf', /application\/x-protobuf/);
testIs('/fonts/Open Sans Bold,Open Sans Regular/0-255.pbf', testIs('/fonts/Open Sans Bold,Open Sans Regular/0-255.pbf',
/application\/x-protobuf/); /application\/x-protobuf/);
testIs('/fonts/Nonsense,Open Sans Bold/0-255.pbf', /application\/x-protobuf/); testIs('/fonts/Nonsense,Open Sans Bold/0-255.pbf', /./, 400);
testIs('/fonts/Nonsense/0-255.pbf', /./, 400); testIs('/fonts/Nonsense/0-255.pbf', /./, 400);
testIs('/fonts/Nonsense1,Nonsense2/0-255.pbf', /./, 400); testIs('/fonts/Nonsense1,Nonsense2/0-255.pbf', /./, 400);