Skip to content

Commit 66109b7

Browse files
authored
Merge pull request #1250 from openlayers/transformrequest-response
Accept Response and Promise<Response> as transformRequest return
2 parents 534eddc + 7e7f6d2 commit 66109b7

File tree

7 files changed

+75
-56
lines changed

7 files changed

+75
-56
lines changed

examples/pmtiles.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import 'ol/ol.css';
22
import {apply} from 'ol-mapbox-style';
3-
import {register as registerPMTiles} from 'pmtiles-protocol';
3+
import {fetch} from 'pmtiles-protocol';
44

5-
registerPMTiles();
6-
7-
apply('map', 'data/protomaps-dark-style.json');
5+
apply('map', 'data/protomaps-dark-style.json', {
6+
transformRequest: (url) => fetch(url),
7+
});

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
"mini-css-extract-plugin": "^2.4.4",
7575
"mocha": "^11.1.0",
7676
"nanoassert": "^2.0.0",
77-
"pmtiles-protocol": "^1.0.1",
77+
"pmtiles-protocol": "^1.0.5",
7878
"proj4": "^2.15.0",
7979
"puppeteer": "^23.10.4",
8080
"rollup": "^2.70.2",

src/apply.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,10 @@ import {
6666
/**
6767
* @typedef {Object} Options
6868
* @property {string} [accessToken] Access token for 'mapbox://' urls.
69-
* @property {function(string, import("./util.js").ResourceType): (Request|string|Promise<Request|string>|void)} [transformRequest]
69+
* @property {function(string, import("./util.js").ResourceType): (Request|string|Response|Promise<Request|string|Response>|void)} [transformRequest]
7070
* Function for controlling how `ol-mapbox-style` fetches resources. Can be used for modifying
7171
* the url, adding headers or setting credentials options. Called with the url and the resource
72-
* type as arguments, this function is supposed to return a `Request` or a url `string`, or a promise tehereof.
72+
* type as arguments, this function is supposed to return a `Request`, a url `string` or a `Response`, or a promise tehereof.
7373
* Without a return value the original request will not be modified.
7474
* @property {string} [projection='EPSG:3857'] Only useful when working with non-standard projections.
7575
* Code of a projection registered with OpenLayers. All sources of the style must be provided in this

src/mapbox.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ const mapboxSubdomains = ['a', 'b', 'c', 'd'];
6969
* @private
7070
*/
7171
export function normalizeSourceUrl(url, token, tokenParam, styleUrl) {
72-
const urlObject = new URL(url, styleUrl);
72+
const urlObject = new URL(url, styleUrl || location.href);
7373
const mapboxPath = getMapboxPath(url);
7474
if (!mapboxPath) {
7575
if (!token) {

src/util.js

Lines changed: 62 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -111,45 +111,51 @@ const pendingRequests = {};
111111
* @param {ResourceType} resourceType Type of resource to load.
112112
* @param {string} url Url of the resource.
113113
* @param {Options} [options] Options.
114-
* @param {{request?: Request}} [metadata] Object to be filled with the request.
114+
* @param {{url?: string}} [metadata] Object to be filled with the request.
115115
* @return {Promise<Object|Response>} Promise that resolves with the loaded resource
116116
* or rejects with the Response object.
117117
* @private
118118
*/
119119
export function fetchResource(resourceType, url, options = {}, metadata) {
120120
if (url in pendingRequests) {
121121
if (metadata) {
122-
metadata.request = pendingRequests[url][0];
122+
metadata.url = pendingRequests[url][0].url;
123123
}
124124
return pendingRequests[url][1];
125125
}
126126
const transformedRequest = options.transformRequest
127127
? options.transformRequest(url, resourceType) || url
128128
: url;
129-
const pendingRequest = toPromise(() => transformedRequest).then(
130-
(transformedRequest) => {
129+
const handleError = function (error) {
130+
delete pendingRequests[url];
131+
return Promise.reject(new Error('Error fetching source ' + url));
132+
};
133+
const handleResponse = function (response) {
134+
delete pendingRequests[url];
135+
return response.ok
136+
? response.json()
137+
: Promise.reject(new Error('Error fetching source ' + url));
138+
};
139+
const pendingRequest = toPromise(() => transformedRequest)
140+
.then((transformedRequest) => {
141+
if (transformedRequest instanceof Response) {
142+
if (metadata) {
143+
metadata.url = transformedRequest.url;
144+
}
145+
return handleResponse(transformedRequest);
146+
}
131147
if (!(transformedRequest instanceof Request)) {
132148
transformedRequest = new Request(transformedRequest);
133149
}
134150
if (!transformedRequest.headers.get('Accept')) {
135151
transformedRequest.headers.set('Accept', 'application/json');
136152
}
137153
if (metadata) {
138-
metadata.request = transformedRequest;
154+
metadata.url = transformedRequest.url;
139155
}
140-
return fetch(transformedRequest)
141-
.then(function (response) {
142-
delete pendingRequests[url];
143-
return response.ok
144-
? response.json()
145-
: Promise.reject(new Error('Error fetching source ' + url));
146-
})
147-
.catch(function (error) {
148-
delete pendingRequests[url];
149-
return Promise.reject(new Error('Error fetching source ' + url));
150-
});
151-
},
152-
);
156+
return fetch(transformedRequest).then(handleResponse).catch(handleError);
157+
})
158+
.catch(handleError);
153159
pendingRequests[url] = [transformedRequest, pendingRequest];
154160
return pendingRequest;
155161
}
@@ -191,38 +197,51 @@ export function getTileJson(glSource, styleUrl, options = {}) {
191197
: src;
192198
if (tile instanceof VectorTile) {
193199
tile.setLoader((extent, resolution, projection) => {
194-
toPromise(() => transformedRequest).then((transformedRequest) => {
195-
fetch(transformedRequest)
196-
.then((response) => response.arrayBuffer())
197-
.then((data) => {
198-
const format = tile.getFormat();
199-
const features = format.readFeatures(data, {
200-
extent: extent,
201-
featureProjection: projection,
202-
});
203-
// @ts-ignore
204-
tile.setFeatures(features);
205-
})
206-
.catch((e) => tile.setState(TileState.ERROR));
207-
});
200+
const handleResponse = function (response) {
201+
response.arrayBuffer().then((data) => {
202+
const format = tile.getFormat();
203+
const features = format.readFeatures(data, {
204+
extent: extent,
205+
featureProjection: projection,
206+
});
207+
// @ts-ignore
208+
tile.setFeatures(features);
209+
});
210+
};
211+
toPromise(() => transformedRequest)
212+
.then((transformedRequest) => {
213+
if (transformedRequest instanceof Response) {
214+
return handleResponse(transformedRequest);
215+
}
216+
fetch(transformedRequest)
217+
.then(handleResponse)
218+
.catch((e) => tile.setState(TileState.ERROR));
219+
})
220+
.catch((e) => tile.setState(TileState.ERROR));
208221
});
209222
} else {
210223
const img = tile.getImage();
211-
toPromise(() => transformedRequest).then((transformedRequest) => {
212-
if (transformedRequest instanceof Request) {
213-
fetch(transformedRequest)
214-
.then((response) => response.blob())
215-
.then((blob) => {
224+
toPromise(() => transformedRequest)
225+
.then((transformedRequest) => {
226+
if (typeof transformedRequest === 'string') {
227+
img.src = transformedRequest;
228+
return;
229+
}
230+
const handleResponse = (response) =>
231+
response.blob().then((blob) => {
216232
const url = URL.createObjectURL(blob);
217233
img.addEventListener('load', () => URL.revokeObjectURL(url));
218234
img.addEventListener('error', () => URL.revokeObjectURL(url));
219235
img.src = url;
220-
})
236+
});
237+
if (transformedRequest instanceof Response) {
238+
return handleResponse(transformedRequest);
239+
}
240+
fetch(transformedRequest)
241+
.then(handleResponse)
221242
.catch((e) => tile.setState(TileState.ERROR));
222-
} else {
223-
img.src = transformedRequest;
224-
}
225-
});
243+
})
244+
.catch((e) => tile.setState(TileState.ERROR));
226245
}
227246
};
228247
}
@@ -258,7 +277,7 @@ export function getTileJson(glSource, styleUrl, options = {}) {
258277
tileUrl,
259278
options.accessToken,
260279
options.accessTokenParam || 'access_token',
261-
metadata.request.url,
280+
metadata.url,
262281
)[0];
263282
});
264283
return Promise.resolve({tileJson, tileLoadFunction});

test/util.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ describe('util', function () {
6464
),
6565
])
6666
.then(() => {
67-
should('request' in metadataPending).true();
67+
should('url' in metadataPending).true();
6868
should(metadataPending.request).equal(metadataNotPending.request);
6969
done();
7070
})

0 commit comments

Comments
 (0)