From 7bdb7afcb9decf67d1e36dbd3a947e29e60f6200 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Wed, 23 Aug 2017 11:14:35 -0400 Subject: [PATCH] Reuse the function for creating empty responses --- src/serve_rendered.js | 145 +++++++++++++++++++----------------------- 1 file changed, 67 insertions(+), 78 deletions(-) diff --git a/src/serve_rendered.js b/src/serve_rendered.js index 42ea19f..5350e07 100644 --- a/src/serve_rendered.js +++ b/src/serve_rendered.js @@ -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) {