Make MapboxVector layer work in more access key scenarios

This commit is contained in:
Andreas Hocevar
2021-11-02 20:45:30 +01:00
parent d1930d4a3f
commit cbac16e21f
2 changed files with 64 additions and 9 deletions

View File

@@ -92,13 +92,16 @@ export function normalizeStyleUrl(url, token) {
* Turns mapbox:// source URLs into vector tile URL templates.
* @param {string} url The source URL.
* @param {string} token The access token.
* @param {string} tokenParam The access token key.
* @return {string} A vector tile template.
* @private
*/
export function normalizeSourceUrl(url, token) {
export function normalizeSourceUrl(url, token, tokenParam) {
const mapboxPath = getMapboxPath(url);
if (!mapboxPath) {
return url;
return token && url.indexOf(token) === -1
? `${url}${url.indexOf('?') === -1 ? '?' : '&'}${tokenParam}=${token}`
: url;
}
return `https://{a-d}.tiles.mapbox.com/v4/${mapboxPath}/{z}/{x}/{y}.vector.pbf?access_token=${token}`;
}
@@ -133,6 +136,7 @@ class ErrorEvent extends BaseEvent {
* @typedef {Object} SourceObject
* @property {string} url The source URL.
* @property {SourceType} type The source type.
* @property {Array<string>} [tiles] TileJSON tiles.
*/
/**
@@ -155,8 +159,8 @@ const SourceType = {
* style created with Mapbox Studio and hosted on Mapbox, this will look like
* 'mapbox://styles/you/your-style'.
* @property {string} [accessToken] The access token for your Mapbox style. This has to be provided
* for `mapbox://` style urls. For `https://` and other urls, access keys must be part of the style
* url.
* for `mapbox://` style urls. For `https://` and other urls, any access key must be the last query
* parameter of the style url.
* @property {string} [source] If your style uses more than one source, you need to use either the
* `source` property or the `layers` property to limit rendering to a single vector source. The
* `source` property corresponds to the id of a vector source in your Mapbox style.
@@ -284,7 +288,16 @@ class MapboxVectorLayer extends VectorTileLayer {
this.sourceId = options.source;
this.layers = options.layers;
this.accessToken = options.accessToken;
if (options.accessToken) {
this.accessToken = options.accessToken;
} else {
const parts = options.styleUrl.split(/[?&]/);
if (parts.length > 1) {
const keyValue = parts[parts.length - 1].split('=');
this.accessToken = keyValue[1];
this.accessTokenParam_ = keyValue[0];
}
}
this.fetchStyle(options.styleUrl);
}
@@ -384,7 +397,13 @@ class MapboxVectorLayer extends VectorTileLayer {
styleSource.url.indexOf('{z}') !== -1
) {
// Tile source url, handle it directly
source.setUrl(normalizeSourceUrl(styleSource.url, this.accessToken));
source.setUrl(
normalizeSourceUrl(
styleSource.url,
this.accessToken,
this.accessTokenParam_
)
);
applyStyle(this, style, sourceIdOrLayersList)
.then(() => {
source.setState(SourceState.READY);
@@ -394,7 +413,19 @@ class MapboxVectorLayer extends VectorTileLayer {
});
} else {
// TileJSON url, let ol-mapbox-style handle it
setupVectorSource(styleSource, styleSource.url).then((source) => {
if (styleSource.tiles) {
styleSource.tiles = styleSource.tiles.map((url) =>
normalizeSourceUrl(url, this.accessToken, this.accessTokenParam_)
);
}
setupVectorSource(
styleSource,
normalizeSourceUrl(
styleSource.url,
this.accessToken,
this.accessTokenParam_
)
).then((source) => {
applyStyle(this, style, sourceIdOrLayersList)
.then(() => {
this.setSource(source);

View File

@@ -80,14 +80,20 @@ describe('ol/layer/MapboxVector', () => {
},
{
url: 'https://example.com/source/{z}/{x}/{y}.pbf',
expected: 'https://example.com/source/{z}/{x}/{y}.pbf',
expected: 'https://example.com/source/{z}/{x}/{y}.pbf?token=test-token',
},
{
url: 'https://example.com/source/{z}/{x}/{y}.pbf?foo=bar',
expected:
'https://example.com/source/{z}/{x}/{y}.pbf?foo=bar&token=test-token',
},
];
const token = 'test-token';
const tokenParam = 'token';
for (const c of cases) {
it(`works for ${c.url}`, () => {
expect(normalizeSourceUrl(c.url, token)).to.be(c.expected);
expect(normalizeSourceUrl(c.url, token, tokenParam)).to.be(c.expected);
});
}
});
@@ -116,4 +122,22 @@ describe('ol/layer/MapboxVector', () => {
});
});
});
describe('Access token', function () {
it('applies correct access token from access_token', function () {
const layer = new MapboxVectorLayer({
styleUrl: 'mapbox://styles/mapbox/streets-v7',
accessToken: '123',
});
expect(layer.accessToken).to.be('123');
expect(layer.accessTokenParam_).to.be(undefined);
});
it('applies correct access token from url', function () {
const layer = new MapboxVectorLayer({
styleUrl: '?key=123',
});
expect(layer.accessToken).to.be('123');
expect(layer.accessTokenParam_).to.be('key');
});
});
});