Compare commits

..

23 Commits
v0.4 ... v0.8.0

Author SHA1 Message Date
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
Petr Sloup
d6e2baef67 Update version to 0.6.0 2016-06-29 20:31:13 +02:00
Petr Sloup
6100013718 Fix serving the same style twice 2016-06-29 20:28:56 +02:00
Petr Sloup
4eea8a91b8 Add favicon.ico 2016-06-29 20:25:36 +02:00
Petr Sloup
d57f9f7a60 Fix and improve xray viewer 2016-06-29 20:23:37 +02:00
Petr Sloup
1307b29ff9 Cleaner implementation of keys 2016-06-29 20:17:58 +02:00
Petr Sloup
a9443edfc6 Update mapbox-gl-js to v0.19.0 2016-06-29 20:08:21 +02:00
Petr Sloup
e6a1bf407c Remove sourceMappingURL 2016-06-29 20:08:09 +02:00
Petr Sloup
0ba2dcce53 Always use http for wmts 2016-06-29 19:55:06 +02:00
Petr Sloup
ebd6662ebb Minor WMTS link bugfix 2016-06-29 16:23:49 +02:00
Petr Sloup
6898be5bea Update version 2016-06-29 16:12:42 +02:00
Petr Sloup
a55b5ad69c Fix viewer vector/raster autodetection 2016-06-29 15:14:51 +02:00
Petr Sloup
1104bf8a57 Add links to WMTS services from index.html 2016-06-29 15:08:56 +02:00
Petr Sloup
1d4503b507 If key present in query, propagate it to other linked urls 2016-06-29 14:57:11 +02:00
Petr Sloup
2d5dccc1e0 Update dependencies 2016-06-28 07:48:30 +02:00
14 changed files with 356 additions and 281 deletions

View File

@@ -4,6 +4,7 @@ MAINTAINER Petr Sloup <petr.sloup@klokantech.com>
RUN apt-get -qq update \
&& DEBIAN_FRONTEND=noninteractive apt-get -y install \
curl \
unzip \
build-essential \
python \
libcairo2-dev \

View File

@@ -1,8 +1,9 @@
{
"name": "tileserver-gl",
"version": "0.0.3",
"version": "0.8.0",
"description": "Map tile server for JSON GL styles - serverside generated raster tiles",
"main": "src/main.js",
"bin": "src/main.js",
"authors": [
"Petr Sloup <petr.sloup@klokantech.com>"
],
@@ -17,9 +18,10 @@
"dependencies": {
"async": "1.5.2",
"advanced-pool": "0.3.2",
"base64url": "1.0.6",
"canvas": "1.4.0",
"clone": "1.0.2",
"color": "0.11.2",
"color": "0.11.3",
"cors": "2.7.1",
"express": "4.14.0",
"handlebars": "4.0.5",
@@ -27,8 +29,8 @@
"mbtiles": "0.9.0",
"morgan": "1.7.0",
"nomnom": "1.8.1",
"request": "2.72.0",
"sharp": "0.15.0",
"request": "2.73.0",
"sharp": "0.15.1",
"sphericalmercator": "1.0.5"
},
"devDependencies": {

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -78,6 +78,11 @@
padding: 5px;
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0A%20%20%3Cpath%20style%3D%27fill%3A%23333333%3B%27%20d%3D%27M%2010%206%20C%209.446%206%209%206.4459904%209%207%20L%209%209%20L%207%209%20C%206.446%209%206%209.446%206%2010%20C%206%2010.554%206.446%2011%207%2011%20L%209%2011%20L%209%2013%20C%209%2013.55401%209.446%2014%2010%2014%20C%2010.554%2014%2011%2013.55401%2011%2013%20L%2011%2011%20L%2013%2011%20C%2013.554%2011%2014%2010.554%2014%2010%20C%2014%209.446%2013.554%209%2013%209%20L%2011%209%20L%2011%207%20C%2011%206.4459904%2010.554%206%2010%206%20z%27%20%2F%3E%0A%3C%2Fsvg%3E%0A");
}
.mapboxgl-ctrl-icon.mapboxgl-ctrl-geolocate {
padding: 5px;
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3Cpath%20style%3D%27fill%3A%23333333%3B%27%20d%3D%27M13%2C7%20L10.5%2C11.75%20L10.25%2C10%20z%20M13.888%2C6.112%20C13.615%2C5.84%2013.382%2C6.076%2012.5%2C6.5%20C10.14%2C7.634%206%2C10%206%2C10%20L9.5%2C10.5%20L10%2C14%20C10%2C14%2012.366%2C9.86%2013.5%2C7.5%20C13.924%2C6.617%2014.16%2C6.385%2013.888%2C6.112%27%2F%3E%3C%2Fsvg%3E");
}
.mapboxgl-ctrl-icon.mapboxgl-ctrl-compass > div.arrow {
width: 20px;
height: 20px;
@@ -106,6 +111,8 @@
.mapboxgl-popup {
position: absolute;
top: 0;
left: 0;
display: -webkit-flex;
display: flex;
will-change: transform;

File diff suppressed because one or more lines are too long

View File

@@ -65,5 +65,3 @@ module.exports=window.L=require("leaflet/dist/leaflet-src");
"use strict";function contains(n,t){if(!t||!t.length)return!1;for(var r=0;r<t.length;r++)if(t[r]===n)return!0;return!1}module.exports={idUrl:function(n,t){-1===n.indexOf("/")?t.loadID(n):t.loadURL(n)},log:function(n){"object"==typeof console&&"function"==typeof console.error&&console.error(n)},strict:function(n,t){if(typeof n!==t)throw new Error("Invalid argument: "+t+" expected")},strict_instance:function(n,t,r){if(!(n instanceof t))throw new Error("Invalid argument: "+r+" expected")},strict_oneof:function(n,t){if(!contains(n,t))throw new Error("Invalid argument: "+n+" given, valid values are "+t.join(", "))},strip_tags:function(n){return n.replace(/<[^<]+>/g,"")},lbounds:function(n){return new L.LatLngBounds([[n[1],n[0]],[n[3],n[2]]])}};
},{}]},{},[17])
//# sourceMappingURL=mapbox.js.map

View File

@@ -4,8 +4,8 @@
<meta charset="UTF-8">
<title>{{name}} - TileServer GL</title>
{{#is_vector}}
<link rel="stylesheet" type="text/css" href="/mapbox-gl.css" />
<script src="/mapbox-gl.js"></script>
<link rel="stylesheet" type="text/css" href="/mapbox-gl.css{{&key_query}}" />
<script src="/mapbox-gl.js{{&key_query}}"></script>
<style>
body {background:#000;color:#ccc;}
#map {position:absolute;top:0;left:0;right:250px;bottom:0;}
@@ -16,9 +16,9 @@
</style>
{{/is_vector}}
{{^is_vector}}
<link rel="stylesheet" type="text/css" href="/mapbox.css" />
<script src="/mapbox.js"></script>
<script src="/leaflet-hash.js"></script>
<link rel="stylesheet" type="text/css" href="/mapbox.css{{&key_query}}" />
<script src="/mapbox.js{{&key_query}}"></script>
<script src="/leaflet-hash.js{{&key_query}}"></script>
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
@@ -97,18 +97,24 @@
}
};
xhttp.responseType = 'json';
xhttp.open('GET', '/data/{{id}}.json', true);
xhttp.open('GET', '/data/{{id}}.json{{&key_query}}', true);
xhttp.send();
var propertyList = document.getElementById('propertyList');
map.on('mousemove', function(e) {
propertyList.innerHTML = '';
map.featuresAt(e.point, {radius: 3}, function(err, features) {
if (err) throw err;
if (features[0]) {
propertyList.innerHTML = JSON.stringify(features[0].properties, null, 2);
}
});
var width = 3, height = 3;
var features = map.queryRenderedFeatures([
[e.point.x - width / 2, e.point.y - height / 2],
[e.point.x + width / 2, e.point.y + height / 2]
]);
if (features) {
var html = '';
features.forEach(function(feature) {
html += JSON.stringify(feature.properties, null, 2) + '\n';
});
propertyList.innerHTML = html;
}
});
</script>
{{/is_vector}}
@@ -116,7 +122,7 @@
<h1 style="display:none;">{{name}}</h1>
<div id='map'></div>
<script>
var map = L.mapbox.map('map', '/data/{{id}}.json', { zoomControl: false });
var map = L.mapbox.map('map', '/data/{{id}}.json{{&key_query}}', { zoomControl: false });
new L.Control.Zoom({ position: 'topright' }).addTo(map);
setTimeout(function() {
new L.Hash(map);

File diff suppressed because one or more lines are too long

View File

@@ -3,11 +3,11 @@
<head>
<meta charset="UTF-8">
<title>{{name}} - TileServer GL</title>
<link rel="stylesheet" type="text/css" href="/mapbox-gl.css" />
<script src="/mapbox-gl.js"></script>
<link rel="stylesheet" type="text/css" href="/mapbox.css" />
<script src="/mapbox.js"></script>
<script src="/leaflet-hash.js"></script>
<link rel="stylesheet" type="text/css" href="/mapbox-gl.css{{&key_query}}" />
<script src="/mapbox-gl.js{{&key_query}}"></script>
<link rel="stylesheet" type="text/css" href="/mapbox.css{{&key_query}}" />
<script src="/mapbox.js{{&key_query}}"></script>
<script src="/leaflet-hash.js{{&key_query}}"></script>
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
@@ -17,19 +17,20 @@
<h1 style="display:none;">{{name}}</h1>
<div id='map'></div>
<script>
var preference = (location.search || '').substr(1);
if (preference != 'vector' && preference != 'raster') {
preference = mapboxgl.supported() ? 'vector' : 'raster';
}
var q = (location.search || '').substr(1).split('&');
var preference =
q.indexOf('vector') >= 0 ? 'vector' :
(q.indexOf('raster') >= 0 ? 'raster' :
(mapboxgl.supported() ? 'vector' : 'raster'));
if (preference == 'vector') {
var map = new mapboxgl.Map({
container: 'map',
style: '/styles/{{id}}.json',
style: '/styles/{{id}}.json{{&key_query}}',
hash: true
});
map.addControl(new mapboxgl.Navigation());
} else {
var map = L.mapbox.map('map', '/styles/{{id}}/rendered.json', { zoomControl: false });
var map = L.mapbox.map('map', '/styles/{{id}}/rendered.json{{&key_query}}', { zoomControl: false });
new L.Control.Zoom({ position: 'topright' }).addTo(map);
setTimeout(function() {
new L.Hash(map);

9
run.sh
View File

@@ -1,2 +1,11 @@
#!/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

View File

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

View File

@@ -2,7 +2,6 @@
var async = require('async'),
advancedPool = require('advanced-pool'),
crypto = require('crypto'),
fs = require('fs'),
path = require('path'),
util = require('util'),
@@ -78,9 +77,6 @@ module.exports = function(options, repo, params, id) {
if (headers['Last-Modified']) {
response.modified = new Date(headers['Last-Modified']);
}
if (headers['ETag']) {
response.etag = headers['ETag'];
}
if (format == 'pbf') {
response.data = zlib.unzipSync(data);
@@ -137,7 +133,7 @@ module.exports = function(options, repo, params, id) {
});
};
styleJSON = require(path.join(options.paths.styles, styleFile));
styleJSON = clone(require(path.join(options.paths.styles, styleFile)));
styleJSON.sprite = 'sprites://' + path.basename(styleFile, '.json');
styleJSON.glyphs = 'fonts://{fontstack}/{range}.pbf';
@@ -292,10 +288,8 @@ module.exports = function(options, repo, params, id) {
return res.status(404).send('Not found');
}
var md5 = crypto.createHash('md5').update(buffer).digest('base64');
res.set({
'content-md5': md5,
'content-type': 'image/' + format
'Content-Type': 'image/' + format
});
return res.status(200).send(buffer);
});

View File

@@ -46,9 +46,13 @@ module.exports = function(options, repo, params, id, reportTiles, reportFont) {
repo[id] = styleJSON;
app.get('/' + id + '.json', function(req, res, next) {
var fixUrl = function(url) {
var fixUrl = function(url, opt_nokey) {
var query = '';
if (!opt_nokey && req.query.key) {
query = '?key=' + req.query.key;
}
return url.replace(
'local://', req.protocol + '://' + req.headers.host + '/');
'local://', req.protocol + '://' + req.headers.host + '/') + query;
};
var styleJSON_ = clone(styleJSON);
@@ -56,7 +60,8 @@ module.exports = function(options, repo, params, id, reportTiles, reportFont) {
var source = styleJSON_.sources[name];
source.url = fixUrl(source.url);
});
styleJSON_.sprite = fixUrl(styleJSON_.sprite);
// mapbox-gl-js viewer cannot handle sprite urls with query
styleJSON_.sprite = fixUrl(styleJSON_.sprite, true);
styleJSON_.glyphs = fixUrl(styleJSON_.glyphs);
return res.send(styleJSON_);
});

View File

@@ -7,20 +7,24 @@ process.env.UV_THREADPOOL_SIZE =
var fs = require('fs'),
path = require('path');
var clone = require('clone'),
var base64url = require('base64url'),
clone = require('clone'),
cors = require('cors'),
express = require('express'),
handlebars = require('handlebars'),
mercator = new (require('sphericalmercator'))(),
morgan = require('morgan');
var serve_font = require('./serve_font'),
var packageJson = require('../package'),
serve_font = require('./serve_font'),
serve_rendered = require('./serve_rendered'),
serve_style = require('./serve_style'),
serve_data = require('./serve_data'),
utils = require('./utils');
module.exports = function(opts, callback) {
console.log('Starting TileServer-GL v' + packageJson.version);
var app = express().disable('x-powered-by'),
serving = {
styles: {},
@@ -45,7 +49,7 @@ module.exports = function(opts, callback) {
var config;
try {
config = require(configPath);
config = clone(require(configPath));
} catch (e) {
console.log('ERROR: Config file not found or invalid!');
console.log(' See README.md for instructions and sample data.');
@@ -118,13 +122,15 @@ module.exports = function(opts, callback) {
app.get('/styles.json', function(req, res, next) {
var result = [];
var query = req.query.key ? ('?key=' + req.query.key) : '';
Object.keys(serving.styles).forEach(function(id) {
var styleJSON = serving.styles[id];
result.push({
version: styleJSON.version,
name: styleJSON.name,
id: id,
url: req.protocol + '://' + req.headers.host + '/styles/' + id + '.json'
url: req.protocol + '://' + req.headers.host +
'/styles/' + id + '.json' + query
});
});
res.send(result);
@@ -165,17 +171,21 @@ module.exports = function(opts, callback) {
app.use(path, function(req, res, next) {
var data = {};
if (dataGetter) {
data = dataGetter(req.params);
data = dataGetter(req);
if (!data) {
return res.status(404).send('Not found');
}
}
data['server_version'] = packageJson.version;
data['key_query_part'] =
req.query.key ? 'key=' + req.query.key + '&amp;' : '';
data['key_query'] = req.query.key ? '?key=' + req.query.key : '';
return res.status(200).send(compiled(data));
});
});
};
serveTemplate('/$', 'index', function() {
serveTemplate('/$', 'index', function(req) {
var styles = clone(config.styles || {});
Object.keys(styles).forEach(function(id) {
var style = styles[id];
@@ -194,6 +204,11 @@ module.exports = function(opts, callback) {
Math.floor(centerPx[0] / 256) + '/' +
Math.floor(centerPx[1] / 256) + '.png';
}
var query = req.query.key ? ('?key=' + req.query.key) : '';
style.wmts_link = 'http://wmts.maptiler.com/' +
base64url('http://' + req.headers.host +
'/styles/' + id + '/rendered.json' + query) + '/wmts';
}
});
var data = clone(serving.data || {});
@@ -213,6 +228,11 @@ module.exports = function(opts, callback) {
Math.floor(centerPx[0] / 256) + '/' +
Math.floor(centerPx[1] / 256) + '.' + data_.format;
}
var query = req.query.key ? ('?key=' + req.query.key) : '';
data_.wmts_link = 'http://wmts.maptiler.com/' +
base64url('http://' + req.headers.host +
'/data/' + id + '.json' + query) + '/wmts';
}
if (data_.filesize) {
var suffix = 'kB';
@@ -234,8 +254,8 @@ module.exports = function(opts, callback) {
};
});
serveTemplate('/styles/:id/$', 'viewer', function(params) {
var id = params.id;
serveTemplate('/styles/:id/$', 'viewer', function(req) {
var id = req.params.id;
var style = clone((config.styles || {})[id]);
if (!style) {
return null;
@@ -253,8 +273,8 @@ module.exports = function(opts, callback) {
});
*/
serveTemplate('/data/:id/$', 'data', function(params) {
var id = params.id;
serveTemplate('/data/:id/$', 'data', function(req) {
var id = req.params.id;
var data = clone(serving.data[id]);
if (!data) {
return null;