@basemaps/lambda-tiler 6.16.0 → 6.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,51 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [6.19.0](https://github.com/linz/basemaps/compare/v6.18.1...v6.19.0) (2021-12-20)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **lambda-tiler:** remove the host check to add api keys for all stylejson sources. ([#2032](https://github.com/linz/basemaps/issues/2032)) ([beab64c](https://github.com/linz/basemaps/commit/beab64c7f747dd5c1be06877b05b1173a95b1537))
12
+
13
+
14
+ ### Features
15
+
16
+ * **lambda-tiler:** compress geojson output to prevent overflowing lambda ([#2034](https://github.com/linz/basemaps/issues/2034)) ([5d48524](https://github.com/linz/basemaps/commit/5d48524c0bf03c40e85cd661fd7f609bbdeed3dd))
17
+ * **tiler:** expose some of the metadata geojson via a /v1/imagery endpoint ([#2033](https://github.com/linz/basemaps/issues/2033)) ([b471209](https://github.com/linz/basemaps/commit/b471209a381dfdab1a25be4882e464c8ddea9064))
18
+
19
+
20
+
21
+
22
+
23
+ # [6.18.0](https://github.com/linz/basemaps/compare/v6.17.0...v6.18.0) (2021-12-14)
24
+
25
+ **Note:** Version bump only for package @basemaps/lambda-tiler
26
+
27
+
28
+
29
+
30
+
31
+ # [6.17.0](https://github.com/linz/basemaps/compare/v6.16.1...v6.17.0) (2021-12-05)
32
+
33
+
34
+ ### Features
35
+
36
+ * **lambda-tiler:** Stop caching for the stylejson. ([#2011](https://github.com/linz/basemaps/issues/2011)) ([f29ae16](https://github.com/linz/basemaps/commit/f29ae16cd0b858fd9929a8cbcefa1c5113687bc9))
37
+ * **landing:** use topographic name not topolike ([#2008](https://github.com/linz/basemaps/issues/2008)) ([a281d87](https://github.com/linz/basemaps/commit/a281d874ae8211447282ad41dd497e96689ceb88))
38
+
39
+
40
+
41
+
42
+
43
+ ## [6.16.1](https://github.com/linz/basemaps/compare/v6.16.0...v6.16.1) (2021-11-30)
44
+
45
+ **Note:** Version bump only for package @basemaps/lambda-tiler
46
+
47
+
48
+
49
+
50
+
6
51
  # [6.16.0](https://github.com/linz/basemaps/compare/v6.15.0...v6.16.0) (2021-11-29)
7
52
 
8
53
 
@@ -172,14 +172,14 @@ o.spec('LambdaXyz', () => {
172
172
  o('should serve tile json for tile_set', async () => {
173
173
  var _a;
174
174
  process.env[Env.PublicUrlBase] = 'https://tiles.test';
175
- const request = mockRequest('/v1/tiles/topolike/Google/tile.json', 'get', apiKeyHeader);
175
+ const request = mockRequest('/v1/tiles/topographic/Google/tile.json', 'get', apiKeyHeader);
176
176
  const res = await handleRequest(request);
177
177
  o(res.status).equals(200);
178
178
  o(res.header('content-type')).equals('application/json');
179
179
  o(res.header('cache-control')).equals('max-age=120');
180
180
  const body = Buffer.from((_a = res.body) !== null && _a !== void 0 ? _a : '', 'base64').toString();
181
181
  o(JSON.parse(body)).deepEquals({
182
- tiles: [`https://tiles.test/v1/tiles/topolike/Google/{z}/{x}/{y}.pbf?api=${apiKey}`],
182
+ tiles: [`https://tiles.test/v1/tiles/topographic/Google/{z}/{x}/{y}.pbf?api=${apiKey}`],
183
183
  minzoom: 0,
184
184
  maxzoom: 15,
185
185
  format: 'pbf',
@@ -194,7 +194,7 @@ o.spec('LambdaXyz', () => {
194
194
  });
195
195
  o('should not found style json', async () => {
196
196
  process.env[Env.PublicUrlBase] = 'https://tiles.test';
197
- const request = mockRequest('/v1/tiles/topolike/Google/style/topolike.json', 'get', apiKeyHeader);
197
+ const request = mockRequest('/v1/tiles/topographic/Google/style/topographic.json', 'get', apiKeyHeader);
198
198
  sandbox.stub(Config.Style, 'get').resolves(null);
199
199
  const res = await handleRequest(request);
200
200
  o(res.status).equals(404);
@@ -203,23 +203,23 @@ o.spec('LambdaXyz', () => {
203
203
  var _a;
204
204
  const host = 'https://tiles.test';
205
205
  process.env[Env.PublicUrlBase] = host;
206
- const request = mockRequest('/v1/tiles/topolike/Google/style/topolike.json', 'get', apiKeyHeader);
206
+ const request = mockRequest('/v1/tiles/topographic/Google/style/topographic.json', 'get', apiKeyHeader);
207
207
  const fakeStyle = {
208
208
  version: 8,
209
209
  id: 'test',
210
- name: 'topolike',
210
+ name: 'topographic',
211
211
  sources: {
212
212
  basemaps_vector: {
213
213
  type: 'vector',
214
- url: `${host}/vector`,
214
+ url: `/vector`,
215
215
  },
216
216
  basemaps_raster: {
217
217
  type: 'raster',
218
- tiles: [`${host}/raster`],
218
+ tiles: [`/raster`],
219
219
  },
220
220
  basemaps_raster_encode: {
221
221
  type: 'raster',
222
- tiles: [`${host}/raster/{z}/{x}/{y}.webp`], // Shouldn't encode the {}
222
+ tiles: [`/raster/{z}/{x}/{y}.webp`], // Shouldn't encode the {}
223
223
  },
224
224
  test_vector: {
225
225
  type: 'vector',
@@ -248,15 +248,15 @@ o.spec('LambdaXyz', () => {
248
248
  metadata: { id: 'test' },
249
249
  };
250
250
  const fakeRecord = {
251
- id: 'st_topolike_production',
252
- name: 'topolike',
251
+ id: 'st_topographic_production',
252
+ name: 'topographic',
253
253
  style: fakeStyle,
254
254
  };
255
255
  sandbox.stub(Config.Style, 'get').resolves(fakeRecord);
256
256
  const res = await handleRequest(request);
257
257
  o(res.status).equals(200);
258
258
  o(res.header('content-type')).equals('application/json');
259
- o(res.header('cache-control')).equals('max-age=120');
259
+ o(res.header('cache-control')).equals('no-store');
260
260
  const body = Buffer.from((_a = res.body) !== null && _a !== void 0 ? _a : '', 'base64').toString();
261
261
  fakeStyle.sources.basemaps_vector = {
262
262
  type: 'vector',
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAe3E,wBAAsB,aAAa,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAavF;AAED,eAAO,MAAM,OAAO,2LAA0C,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAkB3E,wBAAsB,aAAa,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAkBvF;AAED,eAAO,MAAM,OAAO,2LAA0C,CAAC"}
package/build/index.js CHANGED
@@ -4,11 +4,14 @@ import { Ping, Version } from './routes/api.js';
4
4
  import { Health } from './routes/health.js';
5
5
  import { Tiles } from './routes/tile.js';
6
6
  import { Router } from './router.js';
7
+ import { createHash } from 'crypto';
8
+ import { Imagery } from './routes/imagery.js';
7
9
  const app = new Router();
8
10
  app.get('ping', Ping);
9
11
  app.get('health', Health);
10
12
  app.get('version', Version);
11
13
  app.get('tiles', Tiles);
14
+ app.get('imagery', Imagery);
12
15
  let slowTimer = null;
13
16
  export async function handleRequest(req) {
14
17
  // Warn if a request takes more than 10 seconds to process
@@ -18,6 +21,11 @@ export async function handleRequest(req) {
18
21
  slowTimer.unref();
19
22
  req.set('name', 'LambdaTiler');
20
23
  try {
24
+ const apiKey = Router.apiKey(req);
25
+ if (apiKey != null) {
26
+ const apiKeyHash = createHash('sha256').update(apiKey).digest('base64');
27
+ req.set('api', apiKeyHash);
28
+ }
21
29
  return await app.handle(req);
22
30
  }
23
31
  finally {
@@ -0,0 +1,8 @@
1
+ import { LambdaHttpRequest, LambdaHttpResponse } from '@linzjs/lambda';
2
+ /**
3
+ * Get metadata around the imagery such as the source bounding box or the bounding box of the COGS
4
+ * - /v1/imagery/:imageryId/source.geojson
5
+ * - /v1/imagery/:imageryId/covering.geojson
6
+ */
7
+ export declare function Imagery(req: LambdaHttpRequest): Promise<LambdaHttpResponse>;
8
+ //# sourceMappingURL=imagery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"imagery.d.ts","sourceRoot":"","sources":["../../src/routes/imagery.ts"],"names":[],"mappings":"AAEA,OAAO,EAAc,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAgBnF;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA0BjF"}
@@ -0,0 +1,48 @@
1
+ import { Config } from '@basemaps/config';
2
+ import { fsa } from '@basemaps/shared';
3
+ import { HttpHeader, LambdaHttpResponse } from '@linzjs/lambda';
4
+ import { createHash } from 'crypto';
5
+ import { promisify } from 'util';
6
+ import { gzip } from 'zlib';
7
+ import { Router } from '../router.js';
8
+ import { TileEtag } from './tile.etag.js';
9
+ import { NotModified } from './tile.js';
10
+ const gzipP = promisify(gzip);
11
+ function isAllowedFile(f) {
12
+ if (f.endsWith('.geojson'))
13
+ return true;
14
+ if (f.endsWith('.json'))
15
+ return true;
16
+ return false;
17
+ }
18
+ /**
19
+ * Get metadata around the imagery such as the source bounding box or the bounding box of the COGS
20
+ * - /v1/imagery/:imageryId/source.geojson
21
+ * - /v1/imagery/:imageryId/covering.geojson
22
+ */
23
+ export async function Imagery(req) {
24
+ const { rest } = Router.action(req);
25
+ const [imageryId, requestType] = rest;
26
+ if (!isAllowedFile(requestType))
27
+ return new LambdaHttpResponse(404, 'Not found');
28
+ const imagery = await Config.Imagery.get(imageryId);
29
+ if (imagery == null)
30
+ return new LambdaHttpResponse(404, 'Not found');
31
+ const targetPath = fsa.join(imagery.uri, requestType);
32
+ try {
33
+ const buf = await fsa.read(targetPath);
34
+ const cacheKey = createHash('sha256').update(buf).digest('base64');
35
+ if (TileEtag.isNotModified(req, cacheKey))
36
+ return NotModified;
37
+ const response = new LambdaHttpResponse(200, 'ok');
38
+ response.header(HttpHeader.ETag, cacheKey);
39
+ response.header(HttpHeader.ContentEncoding, 'gzip');
40
+ response.buffer(await gzipP(buf), 'application/json');
41
+ req.set('bytes', buf.byteLength);
42
+ return response;
43
+ }
44
+ catch (e) {
45
+ req.log.warn({ targetPath }, 'ImageryMetadata:Failed');
46
+ return new LambdaHttpResponse(404, 'Not found');
47
+ }
48
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"tile.d.ts","sourceRoot":"","sources":["../../src/routes/tile.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAc,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEnF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAIvD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAQtD,eAAO,MAAM,YAAY,gBAA0B,CAAC;AAEpD,eAAO,MAAM,QAAQ,oBAA2C,CAAC;AACjE,eAAO,MAAM,WAAW,oBAA8C,CAAC;AAEvE,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,SAAS;cACJ,iBAAiB,GAAG,QAAQ,kBAAkB,CAAC;2BAelC,MAAM,cAAc,aAAa,GAAG,IAAI,GAAG,QAAQ,aAAa,EAAE,CAAC;cAUhF,iBAAiB,GAAG,QAAQ,kBAAkB,CAAC;kBAiC3C,iBAAiB,GAAG,QAAQ,kBAAkB,CAAC;mBA8B9C,iBAAiB,YAAY,MAAM,GAAG,QAAQ,kBAAkB,CAAC;CA8DvF,CAAC;AACF,wBAAsB,KAAK,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAgB/E"}
1
+ {"version":3,"file":"tile.d.ts","sourceRoot":"","sources":["../../src/routes/tile.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAc,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEnF,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAIvD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAStD,eAAO,MAAM,YAAY,gBAA0B,CAAC;AAEpD,eAAO,MAAM,QAAQ,oBAA2C,CAAC;AACjE,eAAO,MAAM,WAAW,oBAA8C,CAAC;AAEvE,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,SAAS;cACJ,iBAAiB,GAAG,QAAQ,kBAAkB,CAAC;2BAelC,MAAM,cAAc,aAAa,GAAG,IAAI,GAAG,QAAQ,aAAa,EAAE,CAAC;cAUhF,iBAAiB,GAAG,QAAQ,kBAAkB,CAAC;kBAiC3C,iBAAiB,GAAG,QAAQ,kBAAkB,CAAC;mBA8B9C,iBAAiB,YAAY,MAAM,GAAG,QAAQ,kBAAkB,CAAC;CA8DvF,CAAC;AACF,wBAAsB,KAAK,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAY/E"}
@@ -10,6 +10,7 @@ import { TileEtag } from './tile.etag.js';
10
10
  import { Router } from '../router.js';
11
11
  import { ValidateTilePath } from '../validate.js';
12
12
  import { URL } from 'url';
13
+ import { fsa } from '@chunkd/fs';
13
14
  export const TileComposer = new TileMakerSharp(256);
14
15
  export const NotFound = new LambdaHttpResponse(404, 'Not Found');
15
16
  export const NotModified = new LambdaHttpResponse(304, 'Not modified');
@@ -113,8 +114,8 @@ export const TileRoute = {
113
114
  const sources = {};
114
115
  for (const [key, value] of Object.entries(style.sources)) {
115
116
  if (value.type === 'vector') {
116
- if (value.url.includes(host)) {
117
- const url = new URL(value.url);
117
+ if (value.url.startsWith('/')) {
118
+ const url = new URL(fsa.join(host, value.url));
118
119
  url.searchParams.set('api', apiKey);
119
120
  value.url = url.toString().replace(/%7B/g, '{').replace(/%7D/g, '}');
120
121
  }
@@ -122,8 +123,8 @@ export const TileRoute = {
122
123
  else if (value.type === 'raster' && Array.isArray(value.tiles)) {
123
124
  for (let i = 0; i < value.tiles.length; i++) {
124
125
  const tile = value.tiles[i];
125
- if (tile.includes(host)) {
126
- const url = new URL(tile);
126
+ if (tile.startsWith('/')) {
127
+ const url = new URL(fsa.join(host, tile));
127
128
  url.searchParams.set('api', apiKey);
128
129
  value.tiles[i] = url.toString().replace(/%7B/g, '{').replace(/%7D/g, '}');
129
130
  }
@@ -150,7 +151,7 @@ export const TileRoute = {
150
151
  return NotModified;
151
152
  const response = new LambdaHttpResponse(200, 'ok');
152
153
  response.header(HttpHeader.ETag, cacheKey);
153
- response.header(HttpHeader.CacheControl, 'max-age=120');
154
+ response.header(HttpHeader.CacheControl, 'no-store');
154
155
  response.buffer(data, 'application/json');
155
156
  req.set('bytes', data.byteLength);
156
157
  return response;
@@ -161,10 +162,6 @@ export async function Tiles(req) {
161
162
  if (rest.length < 1)
162
163
  return NotFound;
163
164
  const apiKey = Router.apiKey(req);
164
- const apiKeyHash = createHash('sha256')
165
- .update(apiKey !== null && apiKey !== void 0 ? apiKey : '')
166
- .digest('base64');
167
- req.set('api', apiKeyHash);
168
165
  if (!isValidApiKey(apiKey))
169
166
  return new LambdaHttpResponse(400, 'Invalid API Key');
170
167
  const fileName = rest[rest.length - 1].toLowerCase();