diff --git a/common/api-review/database.api.md b/common/api-review/database.api.md index 91176e88388..c20666578f4 100644 --- a/common/api-review/database.api.md +++ b/common/api-review/database.api.md @@ -4,7 +4,7 @@ ```ts -import { FirebaseApp } from '@firebase/app-types'; +import { FirebaseApp } from '@firebase/app'; // @public (undocumented) export interface Database { diff --git a/packages/database/src/core/RepoInfo.ts b/packages/database/src/core/RepoInfo.ts index 54ccafcb092..0ccb647190e 100644 --- a/packages/database/src/core/RepoInfo.ts +++ b/packages/database/src/core/RepoInfo.ts @@ -24,8 +24,8 @@ import { each } from './util/util'; * A class that holds metadata about a Repo object */ export class RepoInfo { - host: string; - domain: string; + private _host: string; + private _domain: string; internalHost: string; /** @@ -45,77 +45,36 @@ export class RepoInfo { public readonly persistenceKey: string = '', public readonly includeNamespaceInQueryParams: boolean = false ) { - this.host = host.toLowerCase(); - this.domain = this.host.substr(this.host.indexOf('.') + 1); + this._host = host.toLowerCase(); + this._domain = this._host.substr(this._host.indexOf('.') + 1); this.internalHost = - (PersistentStorage.get('host:' + host) as string) || this.host; - } - - needsQueryParam(): boolean { - return ( - this.host !== this.internalHost || - this.isCustomHost() || - this.includeNamespaceInQueryParams - ); + (PersistentStorage.get('host:' + host) as string) || this._host; } isCacheableHost(): boolean { return this.internalHost.substr(0, 2) === 's-'; } - isDemoHost() { - return this.domain === 'firebaseio-demo.com'; - } - isCustomHost() { return ( - this.domain !== 'firebaseio.com' && this.domain !== 'firebaseio-demo.com' + this._domain !== 'firebaseio.com' && + this._domain !== 'firebaseio-demo.com' ); } - updateHost(newHost: string) { + get host() { + return this._host; + } + + set host(newHost: string) { if (newHost !== this.internalHost) { this.internalHost = newHost; if (this.isCacheableHost()) { - PersistentStorage.set('host:' + this.host, this.internalHost); + PersistentStorage.set('host:' + this._host, this.internalHost); } } } - /** - * Returns the websocket URL for this repo - * @param type of connection - * @param params list - * @return The URL for this repo - */ - connectionURL(type: string, params: { [k: string]: string }): string { - assert(typeof type === 'string', 'typeof type must == string'); - assert(typeof params === 'object', 'typeof params must == object'); - - let connURL: string; - if (type === WEBSOCKET) { - connURL = - (this.secure ? 'wss://' : 'ws://') + this.internalHost + '/.ws?'; - } else if (type === LONG_POLLING) { - connURL = - (this.secure ? 'https://' : 'http://') + this.internalHost + '/.lp?'; - } else { - throw new Error('Unknown connection type: ' + type); - } - if (this.needsQueryParam()) { - params['ns'] = this.namespace; - } - - const pairs: string[] = []; - - each(params, (key: string, value: string) => { - pairs.push(key + '=' + value); - }); - - return connURL + pairs.join('&'); - } - - /** @return {string} */ toString(): string { let str = this.toURLString(); if (this.persistenceKey) { @@ -124,7 +83,6 @@ export class RepoInfo { return str; } - /** @return {string} */ toURLString(): string { const protocol = this.secure ? 'https://' : 'http://'; const query = this.includeNamespaceInQueryParams @@ -133,3 +91,51 @@ export class RepoInfo { return `${protocol}${this.host}/${query}`; } } + +function repoInfoNeedsQueryParam(repoInfo: RepoInfo): boolean { + return ( + repoInfo.host !== repoInfo.internalHost || + repoInfo.isCustomHost() || + repoInfo.includeNamespaceInQueryParams + ); +} + +/** + * Returns the websocket URL for this repo + * @param repoInfo - RepoInfo object + * @param type - of connection + * @param params - list + * @returns The URL for this repo + */ +export function repoInfoConnectionURL( + repoInfo: RepoInfo, + type: string, + params: { [k: string]: string } +): string { + assert(typeof type === 'string', 'typeof type must == string'); + assert(typeof params === 'object', 'typeof params must == object'); + + let connURL: string; + if (type === WEBSOCKET) { + connURL = + (repoInfo.secure ? 'wss://' : 'ws://') + repoInfo.internalHost + '/.ws?'; + } else if (type === LONG_POLLING) { + connURL = + (repoInfo.secure ? 'https://' : 'http://') + + repoInfo.internalHost + + '/.lp?'; + } else { + throw new Error('Unknown connection type: ' + type); + } + if (repoInfoNeedsQueryParam(repoInfo)) { + params['ns'] = repoInfo.namespace; + } + + const pairs: string[] = []; + + each(params, (key: string, value: string) => { + pairs.push(key + '=' + value); + }); + + return connURL + pairs.join('&'); +} diff --git a/packages/database/src/realtime/BrowserPollConnection.ts b/packages/database/src/realtime/BrowserPollConnection.ts index 96bda58a3c9..113cb2d6008 100644 --- a/packages/database/src/realtime/BrowserPollConnection.ts +++ b/packages/database/src/realtime/BrowserPollConnection.ts @@ -40,7 +40,7 @@ import { import { base64Encode, stringify, isNodeSdk } from '@firebase/util'; import { Transport } from './Transport'; -import { RepoInfo } from '../core/RepoInfo'; +import { RepoInfo, repoInfoConnectionURL } from '../core/RepoInfo'; import { StatsCollection } from '../core/stats/StatsCollection'; // URL query parameters associated with longpolling @@ -116,7 +116,7 @@ export class BrowserPollConnection implements Transport { this.log_ = logWrapper(connId); this.stats_ = StatsManager.getCollection(repoInfo); this.urlFn = (params: { [k: string]: string }) => - repoInfo.connectionURL(LONG_POLLING, params); + repoInfoConnectionURL(repoInfo, LONG_POLLING, params); } /** diff --git a/packages/database/src/realtime/Connection.ts b/packages/database/src/realtime/Connection.ts index 9bc3a97f751..ad5444145e3 100644 --- a/packages/database/src/realtime/Connection.ts +++ b/packages/database/src/realtime/Connection.ts @@ -378,7 +378,7 @@ export class Connection { const version = handshake.v; const host = handshake.h; this.sessionId = handshake.s; - this.repoInfo_.updateHost(host); + this.repoInfo_.host = host; // if we've already closed the connection, then don't bother trying to progress further if (this.state_ === RealtimeState.CONNECTING) { this.conn_.start(); @@ -425,7 +425,7 @@ export class Connection { private onReset_(host: string) { this.log_('Reset packet received. New host: ' + host); - this.repoInfo_.updateHost(host); + this.repoInfo_.host = host; // TODO: if we're already "connected", we need to trigger a disconnect at the next layer up. // We don't currently support resets after the connection has already been established if (this.state_ === RealtimeState.CONNECTED) { diff --git a/packages/database/src/realtime/WebSocketConnection.ts b/packages/database/src/realtime/WebSocketConnection.ts index 5c02c3ef57c..2bcf6fd6b9e 100644 --- a/packages/database/src/realtime/WebSocketConnection.ts +++ b/packages/database/src/realtime/WebSocketConnection.ts @@ -15,7 +15,7 @@ * limitations under the License. */ -import { RepoInfo } from '../core/RepoInfo'; +import { RepoInfo, repoInfoConnectionURL } from '../core/RepoInfo'; import { assert, jsonEval, stringify, isNodeSdk } from '@firebase/util'; import { logWrapper, splitStringBySize } from '../core/util/util'; import { StatsManager } from '../core/stats/StatsManager'; @@ -124,7 +124,7 @@ export class WebSocketConnection implements Transport { if (lastSessionId) { urlParams[LAST_SESSION_PARAM] = lastSessionId; } - return repoInfo.connectionURL(WEBSOCKET, urlParams); + return repoInfoConnectionURL(repoInfo, WEBSOCKET, urlParams); } /** diff --git a/packages/database/test/repoinfo.test.ts b/packages/database/test/repoinfo.test.ts index 503d84bda52..e799516084e 100644 --- a/packages/database/test/repoinfo.test.ts +++ b/packages/database/test/repoinfo.test.ts @@ -24,6 +24,7 @@ import { WEBSOCKET } from '../src/realtime/Constants'; import { expect } from 'chai'; +import { repoInfoConnectionURL } from '../src/core/RepoInfo'; describe('RepoInfo', () => { it('should return the correct URL', () => { @@ -33,12 +34,16 @@ describe('RepoInfo', () => { urlParams[VERSION_PARAM] = PROTOCOL_VERSION; urlParams[LAST_SESSION_PARAM] = 'test'; - const websocketUrl = repoInfo.connectionURL(WEBSOCKET, urlParams); + const websocketUrl = repoInfoConnectionURL(repoInfo, WEBSOCKET, urlParams); expect(websocketUrl).to.equal( 'wss://test-ns.firebaseio.com/.ws?v=5&ls=test' ); - const longPollingUrl = repoInfo.connectionURL(LONG_POLLING, urlParams); + const longPollingUrl = repoInfoConnectionURL( + repoInfo, + LONG_POLLING, + urlParams + ); expect(longPollingUrl).to.equal( 'https://test-ns.firebaseio.com/.lp?v=5&ls=test' );