This commit is contained in:
Michael Straßburger 2016-12-06 03:10:55 +00:00 committed by GitHub
commit 19cb2f6b8d
10 changed files with 76 additions and 48 deletions

View file

@ -66,6 +66,16 @@ The value of ``root`` is used as prefix for all data types.
You can use this to optionally specify on what domains the rendered tiles are accessible. This can be used for basic load-balancing or to bypass browser's limit for the number of connections per domain.
``baseURL``
-----------
When you run the tile server server behind a load-balancer, the automatic URL generators wont't have the required information to build URLs which point to the correct LB endpoint.
Also, if your load balancer is forwarding a HTTPS connection to the non-HTTPS ``tileserver-gl``, setting the ``baseURL`` is indispensable.
Not compatible with the ``domains`` option.
``formatQuality``
-----------------

View file

@ -1,18 +1,18 @@
@font-face {
font-family: 'OpenSans';
src: url('/fonts/OpenSans-Regular.ttf');
src: url('fonts/OpenSans-Regular.ttf');
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'OpenSans';
src: url('/fonts/OpenSans-Italic.ttf');
src: url('fonts/OpenSans-Italic.ttf');
font-weight: normal;
font-style: italic;
}
@font-face {
font-family: 'OpenSans';
src: url('/fonts/OpenSans-Bold.ttf');
src: url('fonts/OpenSans-Bold.ttf');
font-weight: bold;
font-style: normal;
}
@ -149,21 +149,21 @@ footer a {
body {
background-repeat:no-repeat !important;
background-size: contain !important;
background-image: url(/images/header-map-640px.png);
background-image: url(images/header-map-640px.png);
}
@media only screen and (min-width: 641px) {
body {
background-image: url(/images/header-map-1280px.png);
background-image: url(images/header-map-1280px.png);
}
}
@media only screen and (min-width: 1281px) {
body {
background-image: url(/images/header-map-1600px.png);
background-image: url(images/header-map-1600px.png);
}
}
@media only screen and (min-width: 1601px) {
body {
background-image: url(/images/header-map-2560px.png);
background-image: url(images/header-map-2560px.png);
}
}
@ -209,4 +209,4 @@ body {
.btn:first-child{
padding: 0 20px;
}
}
}

View file

@ -5,8 +5,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{name}} - TileServer GL</title>
{{#is_vector}}
<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="{{baseURL}}/mapbox-gl.css{{&key_query}}" />
<script src="{{baseURL}}/mapbox-gl.js{{&key_query}}"></script>
<style>
body {background:#000;color:#ccc;}
#map {position:absolute;top:0;left:0;right:250px;bottom:0;}
@ -17,9 +17,9 @@
</style>
{{/is_vector}}
{{^is_vector}}
<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>
<link rel="stylesheet" type="text/css" href="{{baseURL}}/mapbox.css{{&key_query}}" />
<script src="{{baseURL}}/mapbox.js{{&key_query}}"></script>
<script src="{{baseURL}}/leaflet-hash.js{{&key_query}}"></script>
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
@ -108,7 +108,7 @@
}
};
xhttp.responseType = 'json';
xhttp.open('GET', '/data/{{id}}.json{{&key_query}}', true);
xhttp.open('GET', '{{baseURL}}/data/{{id}}.json{{&key_query}}', true);
xhttp.send();
var propertyList = document.getElementById('propertyList');
@ -133,7 +133,7 @@
<h1 style="display:none;">{{name}}</h1>
<div id='map'></div>
<script>
var map = L.mapbox.map('map', '/data/{{id}}.json{{&key_query}}', { zoomControl: false });
var map = L.mapbox.map('map', '{{baseURL}}/data/{{id}}.json{{&key_query}}', { zoomControl: false });
map.eachLayer(function(layer) {
// do not add scale prefix even if retina display is detected
layer.scalePrefix = '.';

View file

@ -4,7 +4,7 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>TileServer GL - Server for vector and raster maps with GL styles</title>
<link rel="stylesheet" type="text/css" href="/index.css{{&key_query}}" />
<link rel="stylesheet" type="text/css" href="{{baseURL}}/index.css{{&key_query}}" />
<script>
function toggle_xyz(id) {
var el = document.getElementById(id);
@ -17,23 +17,23 @@
</head>
<body>
<section>
<h1 class="title {{#if is_light}}light{{/if}}"><img src="/images/logo.png" alt="TileServer GL" /></h1>
<h1 class="title {{#if is_light}}light{{/if}}"><img src="{{baseURL}}/images/logo.png" alt="TileServer GL" /></h1>
<h2 class="subtitle">Vector {{#if is_light}}<s>and raster</s>{{else}}and raster{{/if}} maps with GL styles</h2>
<h2 class="box-header">Styles</h2>
<div class="box">
{{#each styles}}
<div class="item">
{{#if thumbnail}}
<img src="/styles/{{@key}}/rendered/{{thumbnail}}{{&../key_query}}" alt="{{name}} preview" />
<img src="{{baseURL}}/styles/{{@key}}/rendered/{{thumbnail}}{{&../key_query}}" alt="{{name}} preview" />
{{else}}
<img src="/images/placeholder.png" alt="{{name}} preview" />
<img src="{{baseURL}}/images/placeholder.png" alt="{{name}} preview" />
{{/if}}
<div class="details">
<h3>{{name}}</h3>
<p class="identifier">identifier: {{@key}}</p>
<p class="services">
{{#if serving_rendered}}
services: <a href="/styles/{{@key}}/rendered.json{{&../key_query}}">TileJSON</a>
services: <a href="{{baseURL}}/styles/{{@key}}/rendered.json{{&../key_query}}">TileJSON</a>
{{/if}}
{{#if wmts_link}}
| <a href="{{&wmts_link}}">WMTS</a>
@ -47,14 +47,14 @@
<div class="viewers">
{{#if serving_data}}
{{#if serving_rendered}}
<a class="btn" href="/styles/{{@key}}/{{&../key_query}}{{viewer_hash}}">Viewer</a>
<a class="btn" href="{{baseURL}}/styles/{{@key}}/{{&../key_query}}{{viewer_hash}}">Viewer</a>
{{/if}}
{{/if}}
{{#if serving_rendered}}
<a class="btn" href="/styles/{{@key}}/?{{&../key_query_part}}raster{{viewer_hash}}">Raster</a>
<a class="btn" href="{{baseURL}}/styles/{{@key}}/?{{&../key_query_part}}raster{{viewer_hash}}">Raster</a>
{{/if}}
{{#if serving_data}}
<a class="btn" href="/styles/{{@key}}/?{{&../key_query_part}}vector{{viewer_hash}}">Vector</a>
<a class="btn" href="{{baseURL}}/styles/{{@key}}/?{{&../key_query_part}}vector{{viewer_hash}}">Vector</a>
{{/if}}
</div>
</div>
@ -65,15 +65,15 @@
{{#each data}}
<div class="item">
{{#if thumbnail}}
<img src="/data/{{@key}}/{{thumbnail}}{{&../key_query}}" alt="{{name}} preview" />
<img src="{{baseURL}}/data/{{@key}}/{{thumbnail}}{{&../key_query}}" alt="{{name}} preview" />
{{else}}
<img src="/images/placeholder.png" alt="{{name}} preview" />
<img src="{{baseURL}}/images/placeholder.png" alt="{{name}} preview" />
{{/if}}
<div class="details">
<h3>{{name}}</h3>
<p class="identifier">identifier: {{@key}}{{#if formatted_filesize}} | size: {{formatted_filesize}}{{/if}} | type: {{#is_vector}}vector{{/is_vector}}{{^is_vector}}raster{{/is_vector}} data</p>
<p class="services">
services: <a href="/data/{{@key}}.json{{&../key_query}}">TileJSON</a>
services: <a href="{{baseURL}}/data/{{@key}}.json{{&../key_query}}">TileJSON</a>
{{#if wmts_link}}
| <a href="{{&wmts_link}}">WMTS</a>
{{/if}}
@ -85,10 +85,10 @@
</div>
<div class="viewers">
{{#is_vector}}
<a class="btn" href="/data/{{@key}}/{{&../key_query}}{{viewer_hash}}">X-Ray view</a>
<a class="btn" href="{{baseURL}}/data/{{@key}}/{{&../key_query}}{{viewer_hash}}">X-Ray view</a>
{{/is_vector}}
{{^is_vector}}
<a class="btn" href="/data/{{@key}}/{{&../key_query}}{{viewer_hash}}">Raster view</a>
<a class="btn" href="{{baseURL}}/data/{{@key}}/{{&../key_query}}{{viewer_hash}}">Raster view</a>
{{/is_vector}}
</div>
</div>
@ -96,7 +96,7 @@
</div>
</section>
<footer>
<a href="https://www.klokantech.com/" target="_blank"><img src="/images/klokantech.png" /></a>
<a href="https://www.klokantech.com/" target="_blank"><img src="{{baseURL}}/images/klokantech.png" /></a>
<p>
<a href="https://github.com/klokantech/tileserver-gl" target="_blank">Powered by TileServer GL ({{server_version}})</a> <a href="https://www.klokantech.com/" target="_blank">open-source project from Klokan Technologies GmbH.</a>
</p>

View file

@ -4,11 +4,11 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{{name}} - TileServer GL</title>
<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="{{baseURL}}/mapbox-gl.css{{&key_query}}" />
<script src="{{baseURL}}/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>
<script src="{{baseURL}}/mapbox.js{{&key_query}}"></script>
<script src="{{baseURL}}/leaflet-hash.js{{&key_query}}"></script>
<style>
body { margin:0; padding:0; }
#map { position:absolute; top:0; bottom:0; width:100%; }
@ -26,12 +26,12 @@
if (preference == 'vector') {
var map = new mapboxgl.Map({
container: 'map',
style: '/styles/{{id}}.json{{&key_query}}',
style: '{{baseURL}}/styles/{{id}}.json{{&key_query}}',
hash: true
});
map.addControl(new mapboxgl.Navigation());
} else {
var map = L.mapbox.map('map', '/styles/{{id}}/rendered.json{{&key_query}}', { zoomControl: false });
var map = L.mapbox.map('map', '{{baseURL}}/styles/{{id}}/rendered.json{{&key_query}}', { zoomControl: false });
new L.Control.Zoom({ position: 'topright' }).addTo(map);
setTimeout(function() {
new L.Hash(map);

View file

@ -13,6 +13,7 @@ module.exports = function(options, repo, params, id) {
var app = express().disable('x-powered-by');
var mbtilesFile = path.resolve(options.paths.mbtiles, params.mbtiles);
var baseURL = options.baseURL;
var tileJSON = {
'tiles': params.domains || options.domains
};
@ -81,7 +82,7 @@ module.exports = function(options, repo, params, id) {
app.get('/' + id + '.json', function(req, res, next) {
var info = clone(tileJSON);
info.tiles = utils.getTileUrls(req, info.tiles,
'data/' + id, info.format);
'data/' + id, info.format, baseURL);
return res.send(info);
});

View file

@ -42,6 +42,7 @@ module.exports = function(options, repo, params, id, dataResolver) {
var lastModified = new Date().toUTCString();
var rootPath = options.paths.root;
var baseURL = options.baseURL;
var styleFile = params.style;
var map = {
@ -564,7 +565,7 @@ module.exports = function(options, repo, params, id, dataResolver) {
app.get('/rendered.json', function(req, res, next) {
var info = clone(tileJSON);
info.tiles = utils.getTileUrls(req, info.tiles,
'styles/' + id + '/rendered', info.format);
'styles/' + id + '/rendered', info.format, baseURL);
return res.send(info);
});

View file

@ -12,6 +12,8 @@ module.exports = function(options, repo, params, id, reportTiles, reportFont) {
var styleFile = path.join(options.paths.styles, params.style);
var baseURL = options.baseURL;
var styleJSON = clone(require(styleFile));
Object.keys(styleJSON.sources).forEach(function(name) {
var source = styleJSON.sources[name];
@ -57,8 +59,8 @@ module.exports = function(options, repo, params, id, reportTiles, reportFont) {
if (!opt_nokey && req.query.key) {
query = '?key=' + req.query.key;
}
return url.replace(
'local://', req.protocol + '://' + req.headers.host + '/') + query;
return url.replace('local://',
(baseURL ? baseURL : req.protocol + '://' + req.headers.host) + '/') + query;
};
var styleJSON_ = clone(styleJSON);

View file

@ -69,6 +69,8 @@ module.exports = function(opts, callback) {
}
var options = config.options || {};
var baseURL = options.baseURL;
var paths = options.paths || {};
options.paths = paths;
paths.root = path.resolve(
@ -165,7 +167,7 @@ module.exports = function(opts, callback) {
version: styleJSON.version,
name: styleJSON.name,
id: id,
url: req.protocol + '://' + req.headers.host +
url: (baseURL ? baseURL : req.protocol + '://' + req.headers.host) +
'/styles/' + id + '.json' + query
});
});
@ -176,7 +178,7 @@ module.exports = function(opts, callback) {
Object.keys(serving[type]).forEach(function(id) {
var info = clone(serving[type][id]);
info.tiles = utils.getTileUrls(req, info.tiles,
type + '/' + id, info.format);
type + '/' + id, info.format, baseURL);
arr.push(info);
});
return arr;
@ -224,6 +226,7 @@ module.exports = function(opts, callback) {
serveTemplate('/$', 'index', function(req) {
var styles = clone(config.styles || {});
Object.keys(styles).forEach(function(id) {
var style = styles[id];
style.name = (serving.styles[id] || serving.rendered[id] || {}).name;
@ -247,10 +250,12 @@ module.exports = function(opts, callback) {
base64url('http://' + req.headers.host +
'/styles/' + id + '/rendered.json' + query) + '/wmts';
var tiles = utils.getTileUrls(
req, style.serving_rendered.tiles,
'styles/' + id + '/rendered', style.serving_rendered.format);
'styles/' + id + '/rendered', style.serving_rendered.format, baseURL);
style.xyz_link = tiles[0];
style.baseURL = baseURL;
}
});
var data = clone(serving.data || {});
@ -277,7 +282,7 @@ module.exports = function(opts, callback) {
'/data/' + id + '.json' + query) + '/wmts';
var tiles = utils.getTileUrls(
req, data_.tiles, 'data/' + id, data_.format);
req, data_.tiles, 'data/' + id, data_.format, baseURL);
data_.xyz_link = tiles[0];
}
if (data_.filesize) {
@ -292,11 +297,13 @@ module.exports = function(opts, callback) {
size /= 1024;
}
data_.formatted_filesize = size.toFixed(2) + ' ' + suffix;
data_.baseURL = baseURL;
}
});
return {
styles: styles,
data: data
data: data,
baseURL: baseURL
};
});
@ -310,6 +317,7 @@ module.exports = function(opts, callback) {
style.name = (serving.styles[id] || serving.rendered[id]).name;
style.serving_data = serving.styles[id];
style.serving_rendered = serving.rendered[id];
style.baseURL = baseURL;
return style;
});
@ -327,6 +335,8 @@ module.exports = function(opts, callback) {
}
data.id = id;
data.is_vector = data.format == 'pbf';
data.baseURL = baseURL;
return data;
});

View file

@ -6,20 +6,24 @@ var async = require('async'),
var glyphCompose = require('glyph-pbf-composite');
module.exports.getTileUrls = function(req, domains, path, format) {
module.exports.getTileUrls = function(req, domains, path, format, baseURL) {
var key = req.query.key;
var query = (key && key.length > 0) ? ('?key=' + key) : '';
if (baseURL) {
return [baseURL + '/' + path + '/{z}/{x}/{y}.' + format + query]
}
if (domains) {
if (domains.constructor === String && domains.length > 0) {
domains = domains.split(',');
}
}
if (!domains || domains.length == 0) {
domains = [req.headers.host];
}
var key = req.query.key;
var query = (key && key.length > 0) ? ('?key=' + key) : '';
var uris = [];
domains.forEach(function(domain) {
uris.push(req.protocol + '://' + domain + '/' + path +