UNPKG

3d-tiles-renderer

Version:

https://github.com/AnalyticalGraphicsInc/3d-tiles/tree/master/specification

240 lines (150 loc) 5.09 kB
import { GoogleCloudAuthPlugin } from './GoogleCloudAuthPlugin.js'; import { TMSTilesPlugin } from './images/EPSGTilesPlugin.js'; import { QuantizedMeshPlugin } from './QuantizedMeshPlugin.js'; export class CesiumIonAuthPlugin { constructor( { apiToken, assetId = null, autoRefreshToken = false, useRecommendedSettings = true } ) { this.name = 'CESIUM_ION_AUTH_PLUGIN'; this.priority = - Infinity; this.apiToken = apiToken; this.assetId = assetId; this.autoRefreshToken = autoRefreshToken; this.useRecommendedSettings = useRecommendedSettings; this.tiles = null; this.endpointURL = null; this._bearerToken = null; this._tileSetVersion = - 1; this._tokenRefreshPromise = null; this._attributions = []; this._disposed = false; } init( tiles ) { if ( this.assetId !== null ) { tiles.rootURL = `https://api.cesium.com/v1/assets/${ this.assetId }/endpoint`; } this.tiles = tiles; this.endpointURL = tiles.rootURL; // reset the tiles in case this plugin was removed and re-added tiles.resetFailedTiles(); } loadRootTileSet() { // ensure we have an up-to-date token and root url, then trigger the internal // root tile set load function return this._refreshToken() .then( () => { return this.tiles.invokeOnePlugin( plugin => plugin !== this && plugin.loadRootTileSet && plugin.loadRootTileSet() ); } ); } preprocessURL( uri ) { uri = new URL( uri ); if ( /^http/.test( uri.protocol ) && this._tileSetVersion != - 1 ) { uri.searchParams.append( 'v', this._tileSetVersion ); } return uri.toString(); } fetchData( uri, options ) { const tiles = this.tiles; if ( tiles.getPluginByName( 'GOOGLE_CLOUD_AUTH_PLUGIN' ) !== null ) { return null; } else { return Promise.resolve().then( async () => { // wait for the token to refresh if loading if ( this._tokenRefreshPromise !== null ) { await this._tokenRefreshPromise; uri = this.preprocessURL( uri ); } const res = await fetch( uri, options ); if ( res.status >= 400 && res.status <= 499 && this.autoRefreshToken ) { await this._refreshToken( options ); return fetch( this.preprocessURL( uri ), options ); } else { return res; } } ); } } getAttributions( target ) { if ( this.tiles.visibleTiles.size > 0 ) { target.push( ...this._attributions ); } } _refreshToken( options ) { if ( this._tokenRefreshPromise === null ) { // construct the url to fetch the endpoint const url = new URL( this.endpointURL ); url.searchParams.append( 'access_token', this.apiToken ); this._tokenRefreshPromise = fetch( url, options ) .then( res => { if ( this._disposed ) { return null; } if ( ! res.ok ) { throw new Error( `CesiumIonAuthPlugin: Failed to load data with error code ${ res.status }` ); } return res.json(); } ) .then( json => { if ( this._disposed ) { return null; } const tiles = this.tiles; if ( 'externalType' in json ) { const url = new URL( json.options.url ); tiles.rootURL = json.options.url; // if the tile set is "external" then assume it's a google API tile set tiles.registerPlugin( new GoogleCloudAuthPlugin( { apiToken: url.searchParams.get( 'key' ), autoRefreshToken: this.autoRefreshToken, useRecommendedSettings: this.useRecommendedSettings, } ) ); } else { // GLTF // CZML // KML // GEOJSON if ( json.type === 'TERRAIN' && tiles.getPluginByName( 'QUANTIZED_MESH_PLUGIN' ) === null ) { tiles.registerPlugin( new QuantizedMeshPlugin( { useRecommendedSettings: this.useRecommendedSettings, } ) ); } else if ( json.type === 'IMAGERY' && tiles.getPluginByName( 'TMS_TILES_PLUGIN' ) === null ) { tiles.registerPlugin( new TMSTilesPlugin( { useRecommendedSettings: this.useRecommendedSettings, shape: 'ellipsoid', } ) ); } tiles.rootURL = json.url; tiles.fetchOptions.headers = tiles.fetchOptions.headers || {}; tiles.fetchOptions.headers.Authorization = `Bearer ${ json.accessToken }`; // save the version key if present if ( url.searchParams.has( 'v' ) && this._tileSetVersion === - 1 ) { const url = new URL( json.url ); this._tileSetVersion = url.searchParams.get( 'v' ); } this._bearerToken = json.accessToken; if ( json.attributions ) { this._attributions = json.attributions.map( att => ( { value: att.html, type: 'html', collapsible: att.collapsible, } ) ); } } this._tokenRefreshPromise = null; return json; } ); // dispatch an error if we fail to refresh the token this._tokenRefreshPromise .catch( error => { this.tiles.dispatchEvent( { type: 'load-error', tile: null, error, url, } ); } ); } return this._tokenRefreshPromise; } dispose() { this._disposed = true; } }