UNPKG

3d-tiles-renderer

Version:

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

167 lines (103 loc) 3.5 kB
import { TraversalUtils } from '3d-tiles-renderer/core'; const TILES_MAP_URL = 'https://tile.googleapis.com/v1/createSession'; // Class for making fetches to Google Cloud, refreshing the token if needed. // Supports both the 2d map tiles API in addition to 3d tiles. export class GoogleCloudAuth { get isMapTilesSession() { return this.authURL === TILES_MAP_URL; } constructor( options = {} ) { const { apiToken, sessionOptions = null, autoRefreshToken = false } = options; this.apiToken = apiToken; this.autoRefreshToken = autoRefreshToken; this.authURL = TILES_MAP_URL; this.sessionToken = null; this.sessionOptions = sessionOptions; this._tokenRefreshPromise = null; } async fetch( url, options ) { // if we're using a map tiles session then we have to refresh the token separately if ( this.sessionToken === null && this.isMapTilesSession ) { this.refreshToken( options ); } await this._tokenRefreshPromise; // construct the url const fetchUrl = new URL( url ); fetchUrl.searchParams.set( 'key', this.apiToken ); if ( this.sessionToken ) { fetchUrl.searchParams.set( 'session', this.sessionToken ); } // try to refresh the session token if we failed to load it let res = await fetch( fetchUrl, options ); if ( res.status >= 400 && res.status <= 499 && this.autoRefreshToken ) { // refresh the session token await this.refreshToken( options ); if ( this.sessionToken ) { fetchUrl.searchParams.set( 'session', this.sessionToken ); } res = await fetch( fetchUrl, options ); } if ( this.sessionToken === null && ! this.isMapTilesSession ) { // if we're using a 3d tiles session then we get the session key in the first request return res .json() .then( json => { this.sessionToken = getSessionToken( json ); return json; } ); } else { return res; } } refreshToken( options ) { if ( this._tokenRefreshPromise === null ) { // construct the url to fetch the endpoint const url = new URL( this.authURL ); url.searchParams.set( 'key', this.apiToken ); // initialize options for map tiles const fetchOptions = { ...options }; if ( this.isMapTilesSession ) { fetchOptions.method = 'POST'; fetchOptions.body = JSON.stringify( this.sessionOptions ); fetchOptions.headers = fetchOptions.headers || {}; fetchOptions.headers = { ...fetchOptions.headers, 'Content-Type': 'application/json', }; } this._tokenRefreshPromise = fetch( url, fetchOptions ) .then( res => { if ( ! res.ok ) { throw new Error( `GoogleCloudAuth: Failed to load data with error code ${ res.status }` ); } return res.json(); } ) .then( json => { this.sessionToken = getSessionToken( json ); this._tokenRefreshPromise = null; return json; } ); } return this._tokenRefreshPromise; } } // Takes a json response from the auth url and extracts the session token function getSessionToken( json ) { if ( 'session' in json ) { // if using the 2d maps api return json.session; } else { // is using the 3d tiles api let sessionToken = null; const root = json.root; TraversalUtils.traverseSet( root, tile => { if ( tile.content && tile.content.uri ) { const [ , params ] = tile.content.uri.split( '?' ); sessionToken = new URLSearchParams( params ).get( 'session' ); return true; } return false; } ); return sessionToken; } }