Reuse the function for creating empty responses

This commit is contained in:
Tim Schaub 2017-08-23 11:14:35 -04:00
parent 2e46700cd9
commit 7bdb7afcb9

View file

@ -36,14 +36,6 @@ mbgl.on('message', function(e) {
}
});
/**
* Cache of response data by sharp output format. The empty string represents
* an unknown or unsupported format.
*/
var cachedErrorResponses = {
'': new Buffer(0)
};
/**
* Lookup of sharp output formats by file extension.
*/
@ -54,24 +46,42 @@ var extensionToFormat = {
'.webp': 'webp'
};
/**
* Cache of response data by sharp output format and color. Entry for empty
* string is for unknown or unsupported formats.
*/
var cachedEmptyResponses = {
'': new Buffer(0)
};
/**
* Create an appropriate mbgl response for http errors.
* @param {Object} req The mbgl req object.
* @param {http.IncomingMessage} res The incoming response.
* @param {string} format The format (a sharp format or 'pbf').
* @param {string} color The background color (or empty string for transparent).
* @param {Function} callback The mbgl callback.
*/
function createErrorResponse(req, res, callback) {
var parts = url.parse(req.url);
var extension = path.extname(parts.pathname).toLowerCase();
var format = extensionToFormat[extension] || '';
var data = cachedErrorResponses[format];
function createEmptyResponse(format, color, callback) {
if (!format || format === 'pbf') {
callback(null, {data: cachedEmptyResponses['']});
return;
}
if (format === 'jpg') {
format = 'jpeg';
}
if (!color) {
color = 'rgba(255,255,255,0)';
}
var cacheKey = format + ',' + color;
var data = cachedEmptyResponses[cacheKey];
if (data) {
callback(null, {data: data});
return;
}
// create an "empty" response image
var color = new Color('rgba(255,255,255,0)');
var color = new Color(color);
var array = color.array();
var channels = array.length == 4 && format != 'jpeg' ? 4 : 3;
sharp(new Buffer(array), {
@ -82,7 +92,7 @@ function createErrorResponse(req, res, callback) {
}
}).toFormat(format).toBuffer(function(err, buffer, info) {
if (!err) {
cachedErrorResponses[format] = buffer;
cachedEmptyResponses[cacheKey] = buffer;
}
callback(null, {data: buffer});
});
@ -162,26 +172,26 @@ module.exports = function(options, repo, params, id, dataResolver) {
source.getTile(z, x, y, function(err, data, headers) {
if (err) {
//console.log('MBTiles error, serving empty', err);
callback(null, { data: source.emptyTile });
} else {
var response = {};
if (headers['Last-Modified']) {
response.modified = new Date(headers['Last-Modified']);
}
if (format == 'pbf') {
response.data = zlib.unzipSync(data);
if (options.dataDecoratorFunc) {
response.data = options.dataDecoratorFunc(
sourceId, 'data', response.data, z, x, y);
}
} else {
response.data = data;
}
callback(null, response);
createEmptyResponse(source.format, source.color, callback);
return;
}
var response = {};
if (headers['Last-Modified']) {
response.modified = new Date(headers['Last-Modified']);
}
if (format == 'pbf') {
response.data = zlib.unzipSync(data);
if (options.dataDecoratorFunc) {
response.data = options.dataDecoratorFunc(
sourceId, 'data', response.data, z, x, y);
}
} else {
response.data = data;
}
callback(null, response);
});
} else if (protocol == 'http' || protocol == 'https') {
request({
@ -189,29 +199,28 @@ module.exports = function(options, repo, params, id, dataResolver) {
encoding: null,
gzip: true
}, function(err, res, body) {
if (err) {
// console.log('HTTP request error', err);
createErrorResponse(req, res, callback);
} else if (res.statusCode == 200) {
var response = {};
if (res.headers.modified) {
response.modified = new Date(res.headers.modified);
}
if (res.headers.expires) {
response.expires = new Date(res.headers.expires);
}
if (res.headers.etag) {
response.etag = res.headers.etag;
}
response.data = body;
callback(null, response);
} else {
// console.log('HTTP response error', req.url, res.statusCode);
createErrorResponse(req, res, callback);
var parts = url.parse(req.url);
var extension = path.extname(parts.pathname).toLowerCase();
var format = extensionToFormat[extension] || '';
if (err || res.statusCode < 200 || res.statusCode >= 300) {
// console.log('HTTP error', err || res.statusCode);
createEmptyResponse(format, '', callback);
return;
}
var response = {};
if (res.headers.modified) {
response.modified = new Date(res.headers.modified);
}
if (res.headers.expires) {
response.expires = new Date(res.headers.expires);
}
if (res.headers.etag) {
response.etag = res.headers.etag;
}
response.data = body;
callback(null, response);
});
}
}
@ -321,26 +330,6 @@ module.exports = function(options, repo, params, id, dataResolver) {
source = options.dataDecoratorFunc(name, 'tilejson', source);
}
if (source.format == 'pbf') {
map.sources[name].emptyTile = new Buffer(0);
} else {
var color = new Color(source.color || 'rgba(255,255,255,0)');
var format = source.format;
if (format == 'jpg') {
format = 'jpeg';
}
var array = color.array();
var channels = array.length == 4 && format != 'jpeg' ? 4 : 3;
sharp(new Buffer(array), {
raw: {
width: 1,
height: 1,
channels: channels
}
}).toFormat(format).toBuffer(function(err, buffer, info) {
map.sources[name].emptyTile = buffer;
});
}
if (!attributionOverride &&
source.attribution && source.attribution.length > 0) {
if (tileJSON.attribution.length > 0) {