Merge pull request #12955 from ahocevar/mapbox-vector-layer
Make MapboxVector layer work in more access key scenarios
This commit is contained in:
@@ -92,13 +92,19 @@ export function normalizeStyleUrl(url, token) {
|
|||||||
* Turns mapbox:// source URLs into vector tile URL templates.
|
* Turns mapbox:// source URLs into vector tile URL templates.
|
||||||
* @param {string} url The source URL.
|
* @param {string} url The source URL.
|
||||||
* @param {string} token The access token.
|
* @param {string} token The access token.
|
||||||
|
* @param {string} tokenParam The access token key.
|
||||||
* @return {string} A vector tile template.
|
* @return {string} A vector tile template.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
export function normalizeSourceUrl(url, token) {
|
export function normalizeSourceUrl(url, token, tokenParam) {
|
||||||
const mapboxPath = getMapboxPath(url);
|
const mapboxPath = getMapboxPath(url);
|
||||||
if (!mapboxPath) {
|
if (!mapboxPath) {
|
||||||
return url;
|
if (!token) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
const urlObject = new URL(url, location.href);
|
||||||
|
urlObject.searchParams.set(tokenParam, token);
|
||||||
|
return decodeURI(urlObject.href);
|
||||||
}
|
}
|
||||||
return `https://{a-d}.tiles.mapbox.com/v4/${mapboxPath}/{z}/{x}/{y}.vector.pbf?access_token=${token}`;
|
return `https://{a-d}.tiles.mapbox.com/v4/${mapboxPath}/{z}/{x}/{y}.vector.pbf?access_token=${token}`;
|
||||||
}
|
}
|
||||||
@@ -133,6 +139,7 @@ class ErrorEvent extends BaseEvent {
|
|||||||
* @typedef {Object} SourceObject
|
* @typedef {Object} SourceObject
|
||||||
* @property {string} url The source URL.
|
* @property {string} url The source URL.
|
||||||
* @property {SourceType} type The source type.
|
* @property {SourceType} type The source type.
|
||||||
|
* @property {Array<string>} [tiles] TileJSON tiles.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -155,8 +162,8 @@ const SourceType = {
|
|||||||
* style created with Mapbox Studio and hosted on Mapbox, this will look like
|
* style created with Mapbox Studio and hosted on Mapbox, this will look like
|
||||||
* 'mapbox://styles/you/your-style'.
|
* 'mapbox://styles/you/your-style'.
|
||||||
* @property {string} [accessToken] The access token for your Mapbox style. This has to be provided
|
* @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
|
* for `mapbox://` style urls. For `https://` and other urls, any access key must be the last query
|
||||||
* url.
|
* parameter of the style url.
|
||||||
* @property {string} [source] If your style uses more than one source, you need to use either the
|
* @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 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.
|
* `source` property corresponds to the id of a vector source in your Mapbox style.
|
||||||
@@ -284,7 +291,16 @@ class MapboxVectorLayer extends VectorTileLayer {
|
|||||||
|
|
||||||
this.sourceId = options.source;
|
this.sourceId = options.source;
|
||||||
this.layers = options.layers;
|
this.layers = options.layers;
|
||||||
this.accessToken = options.accessToken;
|
if (options.accessToken) {
|
||||||
|
this.accessToken = options.accessToken;
|
||||||
|
} else {
|
||||||
|
const url = new URL(options.styleUrl, location.href);
|
||||||
|
// The last search parameter is the access token
|
||||||
|
url.searchParams.forEach((value, key) => {
|
||||||
|
this.accessToken = value;
|
||||||
|
this.accessTokenParam_ = key;
|
||||||
|
});
|
||||||
|
}
|
||||||
this.fetchStyle(options.styleUrl);
|
this.fetchStyle(options.styleUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,7 +400,13 @@ class MapboxVectorLayer extends VectorTileLayer {
|
|||||||
styleSource.url.indexOf('{z}') !== -1
|
styleSource.url.indexOf('{z}') !== -1
|
||||||
) {
|
) {
|
||||||
// Tile source url, handle it directly
|
// 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)
|
applyStyle(this, style, sourceIdOrLayersList)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
source.setState(SourceState.READY);
|
source.setState(SourceState.READY);
|
||||||
@@ -394,7 +416,19 @@ class MapboxVectorLayer extends VectorTileLayer {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// TileJSON url, let ol-mapbox-style handle it
|
// 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)
|
applyStyle(this, style, sourceIdOrLayersList)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.setSource(source);
|
this.setSource(source);
|
||||||
|
|||||||
@@ -80,14 +80,20 @@ describe('ol/layer/MapboxVector', () => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
url: 'https://example.com/source/{z}/{x}/{y}.pbf',
|
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 token = 'test-token';
|
||||||
|
const tokenParam = 'token';
|
||||||
for (const c of cases) {
|
for (const c of cases) {
|
||||||
it(`works for ${c.url}`, () => {
|
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: 'foo?key=123',
|
||||||
|
});
|
||||||
|
expect(layer.accessToken).to.be('123');
|
||||||
|
expect(layer.accessTokenParam_).to.be('key');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user