Skip to content

Commit

Permalink
Support custom tiles source (#30)
Browse files Browse the repository at this point in the history
Resolves #29 

Co-authored-by: @AbelVM, @nyurik, @wipfli
  • Loading branch information
HarelM authored Jun 17, 2021
1 parent 320697e commit 492bec5
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
### Features and improvements

- *...Add new stuff here...*
- Added custom protocol support to allow overriding ajax calls ((#29)[https://github.com/maplibre/maplibre-gl-js/issues/29])
- Added setTransformRequest to map (#159)
- Publish @maplibre/maplibre-gl-style-spec v14.0.0 on NPM (#149)
- Replace link to mapbox on LogoControl by link to maplibre (#151)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "maplibre-gl",
"description": "BSD licensed community fork of mapbox-gl, a WebGL interactive maps library",
"version": "1.14.1-rc.1",
"version": "1.14.1-rc.2",
"main": "dist/maplibre-gl.js",
"style": "dist/maplibre-gl.css",
"license": "BSD-3-Clause",
Expand Down
41 changes: 40 additions & 1 deletion src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,46 @@ declare namespace maplibregl {
* Tiles may still be cached by the browser in some cases.
*/
export function clearStorage(callback?: (err?: Error) => void): void;

/**
* Sets a custom load tile function that will be called when using a source that starts with a custom url schema.
* The example below will be triggered for custom:// urls defined in the sources list in the style definitions.
* The function passed will receive the request parameters and should call the callback with the resulting request,
* for example a pbf vector tile, non-compressed, represented as ArrayBuffer.
* @param {string} customProtocol - the protocol to hook, for example 'custom'
* @param {Function} loadFn - the function to use when trying to fetch a tile specified by the customProtocol
* @example
* // this will fetch a file using the fetch API (this is obviously a non iteresting example...)
* maplibre.addProtocol('custom', (params, callback) => {
fetch(`https://${params.url.split("://")[1]}`)
.then(t => {
if (t.status == 200) {
t.arrayBuffer().then(arr => {
callback(null, arr, null, null);
});
} else {
callback(new Error(`Tile fetch error: ${t.statusText}`));
}
})
.catch(e => {
callback(new Error(e));
});
return { cancel: () => { } };
});
* // the following is an example of a way to return an error when trying to load a tile
* maplibre.addProtocol('custom2', (params, callback) => {
* callback(new Error('someErrorMessage'));
* return { cancel: () => { } };
* });
*/
export function addProtocol(customProtocol: string, loadFn: (requestParameters: RequestParameters, callback: ResponseCallback<any>) => Cancelable);
/**
* Removes a previusly added protocol
* @param {string} customProtocol - the custom protocol to remove registration for
* @example
* maplibregl.removeProtocol('custom');
*/
export function removeProtocol(customProtocol: string);

export function setRTLTextPlugin(pluginURL: string, callback: (error: Error) => void, deferred?: boolean): void;
export function getRTLTextPluginStatus(): PluginStatus;

Expand Down
49 changes: 48 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import WorkerPool from './util/worker_pool';
import {prewarm, clearPrewarmedResources} from './util/global_worker_pool';
import {clearTileCache} from './util/tile_request_cache';
import {PerformanceUtils} from './util/performance';
import type {RequestParameters, ResponseCallback} from './util/ajax';
import type {Cancelable} from './types/cancelable';

const exported = {
version,
Expand Down Expand Up @@ -170,7 +172,52 @@ const exported = {
clearTileCache(callback);
},

workerUrl: ''
workerUrl: '',

/**
* Sets a custom load tile function that will be called when using a source that starts with a custom url schema.
* The example below will be triggered for custom:// urls defined in the sources list in the style definitions.
* The function passed will receive the request parameters and should call the callback with the resulting request,
* for example a pbf vector tile, non-compressed, represented as ArrayBuffer.
* @param {string} customProtocol - the protocol to hook, for example 'custom'
* @param {Function} loadFn - the function to use when trying to fetch a tile specified by the customProtocol
* @example
* // this will fetch a file using the fetch API (this is obviously a non iteresting example...)
* maplibre.addProtocol('custom', (params, callback) => {
fetch(`https://${params.url.split("://")[1]}`)
.then(t => {
if (t.status == 200) {
t.arrayBuffer().then(arr => {
callback(null, arr, null, null);
});
} else {
callback(new Error(`Tile fetch error: ${t.statusText}`));
}
})
.catch(e => {
callback(new Error(e));
});
return { cancel: () => { } };
});
* // the following is an example of a way to return an error when trying to load a tile
* maplibre.addProtocol('custom2', (params, callback) => {
* callback(new Error('someErrorMessage'));
* return { cancel: () => { } };
* });
*/
addProtocol(customProtocol: string, loadFn: (requestParameters: RequestParameters, callback: ResponseCallback<any>) => Cancelable) {
config.REGISTERED_PROTOCOLS[customProtocol] = loadFn;
},

/**
* Removes a previusly added protocol
* @param {string} customProtocol - the custom protocol to remove registration for
* @example
* maplibregl.removeProtocol('custom');
*/
removeProtocol(customProtocol: string) {
delete config.REGISTERED_PROTOCOLS[customProtocol];
}
};

//This gets automatically stripped out in production builds.
Expand Down
10 changes: 10 additions & 0 deletions src/util/ajax.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,16 @@ export const makeRequest = function(requestParameters: RequestParameters, callba
// some versions (see https://bugs.webkit.org/show_bug.cgi?id=174980#c2)
// - Requests for resources with the file:// URI scheme don't work with the Fetch API either. In
// this case we unconditionally use XHR on the current thread since referrers don't matter.
if (/:\/\//.test(requestParameters.url) && !(/^https?:|^file:/.test(requestParameters.url))) {
if (isWorker() && self.worker && self.worker.actor) {
return self.worker.actor.send('getResource', requestParameters, callback);
}
if (!isWorker()) {
const protocol = requestParameters.url.substring(0, requestParameters.url.indexOf('://'));
const action = config.REGISTERED_PROTOCOLS[protocol] || makeFetchRequest;
return action(requestParameters, callback);
}
}
if (!isFileURL(requestParameters.url)) {
if (window.fetch && window.Request && window.AbortController && window.Request.prototype.hasOwnProperty('signal')) {
return makeFetchRequest(requestParameters, callback);
Expand Down
8 changes: 5 additions & 3 deletions src/util/config.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// @flow strict
// @flow

type Config = {|
API_URL: string,
EVENTS_URL: ?string,
FEEDBACK_URL: string,
REQUIRE_ACCESS_TOKEN: boolean,
ACCESS_TOKEN: ?string,
MAX_PARALLEL_IMAGE_REQUESTS: number
MAX_PARALLEL_IMAGE_REQUESTS: number,
REGISTERED_PROTOCOLS: { [string]: any },
|};

const config: Config = {
Expand All @@ -24,7 +25,8 @@ const config: Config = {
FEEDBACK_URL: 'https://apps.mapbox.com/feedback',
REQUIRE_ACCESS_TOKEN: true,
ACCESS_TOKEN: null,
MAX_PARALLEL_IMAGE_REQUESTS: 16
MAX_PARALLEL_IMAGE_REQUESTS: 16,
REGISTERED_PROTOCOLS: {},
};

export default config;

0 comments on commit 492bec5

Please sign in to comment.