Skip to content

Commit ac5aca4

Browse files
authored
[Maps] Use content-encoding header from ES for mvt response (#130417)
* Use content-encoding header from ES for mvt We can't always assume the content-encoding will be gzip. When SSL is enabled in Elasticsearch, the http.compression is disabled by default. We can use the headers from the Elasticsearch response to form the Kibana response. You should have HTTPS enabled to test this PR. Use `yarn es snapshot --ssl` and `yarn start --ssl`.
1 parent 3730dd0 commit ac5aca4

File tree

3 files changed

+23
-13
lines changed

3 files changed

+23
-13
lines changed

x-pack/plugins/maps/server/mvt/get_grid_tile.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import { CoreStart, Logger } from '@kbn/core/server';
99
import type { DataRequestHandlerContext } from '@kbn/data-plugin/server';
10+
import { IncomingHttpHeaders } from 'http';
1011
import { Stream } from 'stream';
1112
import { RENDER_AS } from '../../common/constants';
1213
import { isAbortError } from './util';
@@ -40,7 +41,7 @@ export async function getEsGridTile({
4041
renderAs: RENDER_AS;
4142
gridPrecision: number;
4243
abortController: AbortController;
43-
}): Promise<Stream | null> {
44+
}): Promise<{ stream: Stream | null; headers?: IncomingHttpHeaders }> {
4445
try {
4546
const path = `/${encodeURIComponent(index)}/_mvt/${geometryFieldName}/${z}/${x}/${y}`;
4647
const body = {
@@ -80,13 +81,13 @@ export async function getEsGridTile({
8081
}
8182
);
8283

83-
return tile.body as Stream;
84+
return { stream: tile.body as Stream, headers: tile.headers };
8485
} catch (e) {
8586
if (!isAbortError(e)) {
8687
// These are often circuit breaking exceptions
8788
// Should return a tile with some error message
8889
logger.warn(`Cannot generate ES-grid-tile for ${z}/${x}/${y}: ${e.message}`);
8990
}
90-
return null;
91+
return { stream: null };
9192
}
9293
}

x-pack/plugins/maps/server/mvt/get_tile.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import { CoreStart, Logger } from '@kbn/core/server';
99
import type { DataRequestHandlerContext } from '@kbn/data-plugin/server';
10+
import { IncomingHttpHeaders } from 'http';
1011
import { Stream } from 'stream';
1112
import { isAbortError } from './util';
1213
import { makeExecutionContext } from '../../common/execution_context';
@@ -36,7 +37,7 @@ export async function getEsTile({
3637
logger: Logger;
3738
requestBody: any;
3839
abortController: AbortController;
39-
}): Promise<Stream | null> {
40+
}): Promise<{ stream: Stream | null; headers?: IncomingHttpHeaders }> {
4041
try {
4142
const path = `/${encodeURIComponent(index)}/_mvt/${geometryFieldName}/${z}/${x}/${y}`;
4243

@@ -80,13 +81,13 @@ export async function getEsTile({
8081
}
8182
);
8283

83-
return tile.body as Stream;
84+
return { stream: tile.body as Stream, headers: tile.headers };
8485
} catch (e) {
8586
if (!isAbortError(e)) {
8687
// These are often circuit breaking exceptions
8788
// Should return a tile with some error message
8889
logger.warn(`Cannot generate ES-grid-tile for ${z}/${x}/${y}: ${e.message}`);
8990
}
90-
return null;
91+
return { stream: null };
9192
}
9293
}

x-pack/plugins/maps/server/mvt/mvt_routes.ts

+15-7
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
import { Stream } from 'stream';
9+
import { IncomingHttpHeaders } from 'http';
910
import { schema } from '@kbn/config-schema';
1011
import { CoreStart, KibanaRequest, KibanaResponseFactory, Logger } from '@kbn/core/server';
1112
import { IRouter } from '@kbn/core/server';
@@ -57,7 +58,7 @@ export function initMVTRoutes({
5758

5859
const abortController = makeAbortController(request);
5960

60-
const gzippedTile = await getEsTile({
61+
const { stream, headers } = await getEsTile({
6162
url: `${API_ROOT_PATH}/${MVT_GETTILE_API_PATH}/{z}/{x}/{y}.pbf`,
6263
core,
6364
logger,
@@ -71,7 +72,7 @@ export function initMVTRoutes({
7172
abortController,
7273
});
7374

74-
return sendResponse(response, gzippedTile);
75+
return sendResponse(response, stream, headers);
7576
}
7677
);
7778

@@ -103,7 +104,7 @@ export function initMVTRoutes({
103104

104105
const abortController = makeAbortController(request);
105106

106-
const gzipTileStream = await getEsGridTile({
107+
const { stream, headers } = await getEsGridTile({
107108
url: `${API_ROOT_PATH}/${MVT_GETGRIDTILE_API_PATH}/{z}/{x}/{y}.pbf`,
108109
core,
109110
logger,
@@ -119,20 +120,27 @@ export function initMVTRoutes({
119120
abortController,
120121
});
121122

122-
return sendResponse(response, gzipTileStream);
123+
return sendResponse(response, stream, headers);
123124
}
124125
);
125126
}
126127

127-
function sendResponse(response: KibanaResponseFactory, gzipTileStream: Stream | null) {
128+
function sendResponse(
129+
response: KibanaResponseFactory,
130+
gzipTileStream: Stream | null,
131+
headers?: IncomingHttpHeaders
132+
) {
128133
const cacheControl = `public, max-age=${CACHE_TIMEOUT_SECONDS}`;
129134
const lastModified = `${new Date().toUTCString()}`;
130-
if (gzipTileStream) {
135+
if (gzipTileStream && headers) {
136+
// use the content-encoding and content-length headers from elasticsearch if they exist
137+
const { 'content-length': contentLength, 'content-encoding': contentEncoding } = headers;
131138
return response.ok({
132139
body: gzipTileStream,
133140
headers: {
134141
'content-disposition': 'inline',
135-
'content-encoding': 'gzip',
142+
...(contentLength && { 'content-length': contentLength }),
143+
...(contentEncoding && { 'content-encoding': contentEncoding }),
136144
'Content-Type': 'application/x-protobuf',
137145
'Cache-Control': cacheControl,
138146
'Last-Modified': lastModified,

0 commit comments

Comments
 (0)