Skip to content

Commit d0d97e3

Browse files
authored
Merge pull request #208 from PatrickNausha/handle-uri-extensions
Handle URL parameters and fragments.
2 parents ae8ebcb + e4cce69 commit d0d97e3

File tree

4 files changed

+81
-2
lines changed

4 files changed

+81
-2
lines changed

example/data/tileset-external-with-url-params.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

src/base/TilesRendererBase.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import path from 'path-browserify';
22
import { urlJoin } from '../utilities/urlJoin.js';
3+
import { getUrlExtension } from '../utilities/urlExtension.js';
34
import { LRUCache } from '../utilities/LRUCache.js';
45
import { PriorityQueue } from '../utilities/PriorityQueue.js';
56
import { determineFrustumSet, toggleTiles, skipTraversal, markUsedSetLeaves, traverseSet } from './traverseFunctions.js';
@@ -219,7 +220,8 @@ export class TilesRendererBase {
219220
if ( uri ) {
220221

221222
// "content" should only indicate loadable meshes, not external tile sets
222-
const isExternalTileSet = /\.json$/i.test( tile.content.uri );
223+
const extension = getUrlExtension( tile.content.uri );
224+
const isExternalTileSet = extension && extension.toLowerCase() === 'json';
223225
tile.__externalTileSet = isExternalTileSet;
224226
tile.__contentEmpty = isExternalTileSet;
225227

@@ -556,7 +558,7 @@ export class TilesRendererBase {
556558
}
557559

558560
const uri = parseTile.content.uri;
559-
const extension = uri.split( /\./g ).pop();
561+
const extension = getUrlExtension( uri );
560562

561563
return this.parseTile( buffer, parseTile, extension );
562564

src/utilities/urlExtension.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* Returns the file extension of the path component of a URL
3+
* @param {string} url
4+
* @returns {string} null if no extension found
5+
*/
6+
export function getUrlExtension( url ) {
7+
8+
let parsedUrl;
9+
try {
10+
11+
parsedUrl = new URL( url, 'http://fakehost.com/' );
12+
13+
} catch ( _ ) {
14+
15+
// Ignore invalid URLs
16+
return null;
17+
18+
}
19+
20+
const filename = parsedUrl.pathname.split( '/' ).pop();
21+
const dotIndex = filename.lastIndexOf( '.' );
22+
if ( dotIndex === - 1 || dotIndex === filename.length - 1 ) {
23+
24+
// Has no extension or has trailing . character
25+
return null;
26+
27+
}
28+
29+
const extension = filename.substring( dotIndex + 1 );
30+
return extension;
31+
32+
}

test/urlExtension.test.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { getUrlExtension } from '../src/utilities/urlExtension.js';
2+
3+
describe( 'getUrlExtension', () => {
4+
5+
it.each( [
6+
'https://nasa.gov/foo/bar.baz/tileset.json',
7+
'https://nasa.gov/foo/bar.baz/tileset.json?foo=bar',
8+
'https://nasa.gov/foo/bar.baz/tileset.json?a.b=c.d',
9+
'https://nasa.gov/foo/bar.baz/tileset.json?a.b=c.d#e.f',
10+
'https://nasa.gov/tileset.json',
11+
'https://nasa.gov//tileset.json',
12+
'file:///Users/JaneScientist/code/3DTilesRendererJS/example/b3dmExample.json',
13+
'foo.json',
14+
'/foo/bar.json',
15+
'foo.json?a=b',
16+
'/foo.json',
17+
'/foo/bar.json',
18+
'png.svg.json'
19+
] )( 'parses extensions (%s)', url => {
20+
21+
expect( getUrlExtension( url ) ).toBe( 'json' );
22+
23+
} );
24+
25+
it.each( [
26+
'https://nasa.gov',
27+
'https://nasa.gov/',
28+
'https://nasa.gov/tileset',
29+
'https://nasa.gov/foo/bar.baz/tileset?foo=bar',
30+
'https://nasa.gov/foo/bar.baz/tileset?a.b=c.d',
31+
'https://nasa.gov/tileset',
32+
'https://nasa.gov/tileset.',
33+
'Pleiades',
34+
'.',
35+
'..',
36+
'',
37+
undefined,
38+
] )( 'returns null for values that are not URLs with extensions (%s)', url => {
39+
40+
expect( getUrlExtension( url ) ).toBeNull();
41+
42+
} );
43+
44+
} );

0 commit comments

Comments
 (0)