Skip to content

Commit 492bec5

Browse files
authored
Support custom tiles source (#30)
Resolves #29 Co-authored-by: @AbelVM, @nyurik, @wipfli
1 parent 320697e commit 492bec5

File tree

6 files changed

+105
-6
lines changed

6 files changed

+105
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
### Features and improvements
44

55
- *...Add new stuff here...*
6+
- Added custom protocol support to allow overriding ajax calls ((#29)[https://github.com/maplibre/maplibre-gl-js/issues/29])
67
- Added setTransformRequest to map (#159)
78
- Publish @maplibre/maplibre-gl-style-spec v14.0.0 on NPM (#149)
89
- Replace link to mapbox on LogoControl by link to maplibre (#151)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "maplibre-gl",
33
"description": "BSD licensed community fork of mapbox-gl, a WebGL interactive maps library",
4-
"version": "1.14.1-rc.1",
4+
"version": "1.14.1-rc.2",
55
"main": "dist/maplibre-gl.js",
66
"style": "dist/maplibre-gl.css",
77
"license": "BSD-3-Clause",

src/index.d.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,46 @@ declare namespace maplibregl {
4242
* Tiles may still be cached by the browser in some cases.
4343
*/
4444
export function clearStorage(callback?: (err?: Error) => void): void;
45-
45+
/**
46+
* Sets a custom load tile function that will be called when using a source that starts with a custom url schema.
47+
* The example below will be triggered for custom:// urls defined in the sources list in the style definitions.
48+
* The function passed will receive the request parameters and should call the callback with the resulting request,
49+
* for example a pbf vector tile, non-compressed, represented as ArrayBuffer.
50+
* @param {string} customProtocol - the protocol to hook, for example 'custom'
51+
* @param {Function} loadFn - the function to use when trying to fetch a tile specified by the customProtocol
52+
* @example
53+
* // this will fetch a file using the fetch API (this is obviously a non iteresting example...)
54+
* maplibre.addProtocol('custom', (params, callback) => {
55+
fetch(`https://${params.url.split("://")[1]}`)
56+
.then(t => {
57+
if (t.status == 200) {
58+
t.arrayBuffer().then(arr => {
59+
callback(null, arr, null, null);
60+
});
61+
} else {
62+
callback(new Error(`Tile fetch error: ${t.statusText}`));
63+
}
64+
})
65+
.catch(e => {
66+
callback(new Error(e));
67+
});
68+
return { cancel: () => { } };
69+
});
70+
* // the following is an example of a way to return an error when trying to load a tile
71+
* maplibre.addProtocol('custom2', (params, callback) => {
72+
* callback(new Error('someErrorMessage'));
73+
* return { cancel: () => { } };
74+
* });
75+
*/
76+
export function addProtocol(customProtocol: string, loadFn: (requestParameters: RequestParameters, callback: ResponseCallback<any>) => Cancelable);
77+
/**
78+
* Removes a previusly added protocol
79+
* @param {string} customProtocol - the custom protocol to remove registration for
80+
* @example
81+
* maplibregl.removeProtocol('custom');
82+
*/
83+
export function removeProtocol(customProtocol: string);
84+
4685
export function setRTLTextPlugin(pluginURL: string, callback: (error: Error) => void, deferred?: boolean): void;
4786
export function getRTLTextPluginStatus(): PluginStatus;
4887

src/index.js

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import WorkerPool from './util/worker_pool';
2626
import {prewarm, clearPrewarmedResources} from './util/global_worker_pool';
2727
import {clearTileCache} from './util/tile_request_cache';
2828
import {PerformanceUtils} from './util/performance';
29+
import type {RequestParameters, ResponseCallback} from './util/ajax';
30+
import type {Cancelable} from './types/cancelable';
2931

3032
const exported = {
3133
version,
@@ -170,7 +172,52 @@ const exported = {
170172
clearTileCache(callback);
171173
},
172174

173-
workerUrl: ''
175+
workerUrl: '',
176+
177+
/**
178+
* Sets a custom load tile function that will be called when using a source that starts with a custom url schema.
179+
* The example below will be triggered for custom:// urls defined in the sources list in the style definitions.
180+
* The function passed will receive the request parameters and should call the callback with the resulting request,
181+
* for example a pbf vector tile, non-compressed, represented as ArrayBuffer.
182+
* @param {string} customProtocol - the protocol to hook, for example 'custom'
183+
* @param {Function} loadFn - the function to use when trying to fetch a tile specified by the customProtocol
184+
* @example
185+
* // this will fetch a file using the fetch API (this is obviously a non iteresting example...)
186+
* maplibre.addProtocol('custom', (params, callback) => {
187+
fetch(`https://${params.url.split("://")[1]}`)
188+
.then(t => {
189+
if (t.status == 200) {
190+
t.arrayBuffer().then(arr => {
191+
callback(null, arr, null, null);
192+
});
193+
} else {
194+
callback(new Error(`Tile fetch error: ${t.statusText}`));
195+
}
196+
})
197+
.catch(e => {
198+
callback(new Error(e));
199+
});
200+
return { cancel: () => { } };
201+
});
202+
* // the following is an example of a way to return an error when trying to load a tile
203+
* maplibre.addProtocol('custom2', (params, callback) => {
204+
* callback(new Error('someErrorMessage'));
205+
* return { cancel: () => { } };
206+
* });
207+
*/
208+
addProtocol(customProtocol: string, loadFn: (requestParameters: RequestParameters, callback: ResponseCallback<any>) => Cancelable) {
209+
config.REGISTERED_PROTOCOLS[customProtocol] = loadFn;
210+
},
211+
212+
/**
213+
* Removes a previusly added protocol
214+
* @param {string} customProtocol - the custom protocol to remove registration for
215+
* @example
216+
* maplibregl.removeProtocol('custom');
217+
*/
218+
removeProtocol(customProtocol: string) {
219+
delete config.REGISTERED_PROTOCOLS[customProtocol];
220+
}
174221
};
175222

176223
//This gets automatically stripped out in production builds.

src/util/ajax.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,16 @@ export const makeRequest = function(requestParameters: RequestParameters, callba
242242
// some versions (see https://bugs.webkit.org/show_bug.cgi?id=174980#c2)
243243
// - Requests for resources with the file:// URI scheme don't work with the Fetch API either. In
244244
// this case we unconditionally use XHR on the current thread since referrers don't matter.
245+
if (/:\/\//.test(requestParameters.url) && !(/^https?:|^file:/.test(requestParameters.url))) {
246+
if (isWorker() && self.worker && self.worker.actor) {
247+
return self.worker.actor.send('getResource', requestParameters, callback);
248+
}
249+
if (!isWorker()) {
250+
const protocol = requestParameters.url.substring(0, requestParameters.url.indexOf('://'));
251+
const action = config.REGISTERED_PROTOCOLS[protocol] || makeFetchRequest;
252+
return action(requestParameters, callback);
253+
}
254+
}
245255
if (!isFileURL(requestParameters.url)) {
246256
if (window.fetch && window.Request && window.AbortController && window.Request.prototype.hasOwnProperty('signal')) {
247257
return makeFetchRequest(requestParameters, callback);

src/util/config.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
// @flow strict
1+
// @flow
22

33
type Config = {|
44
API_URL: string,
55
EVENTS_URL: ?string,
66
FEEDBACK_URL: string,
77
REQUIRE_ACCESS_TOKEN: boolean,
88
ACCESS_TOKEN: ?string,
9-
MAX_PARALLEL_IMAGE_REQUESTS: number
9+
MAX_PARALLEL_IMAGE_REQUESTS: number,
10+
REGISTERED_PROTOCOLS: { [string]: any },
1011
|};
1112

1213
const config: Config = {
@@ -24,7 +25,8 @@ const config: Config = {
2425
FEEDBACK_URL: 'https://apps.mapbox.com/feedback',
2526
REQUIRE_ACCESS_TOKEN: true,
2627
ACCESS_TOKEN: null,
27-
MAX_PARALLEL_IMAGE_REQUESTS: 16
28+
MAX_PARALLEL_IMAGE_REQUESTS: 16,
29+
REGISTERED_PROTOCOLS: {},
2830
};
2931

3032
export default config;

0 commit comments

Comments
 (0)