diff --git a/.changeset/honest-hounds-sin.md b/.changeset/honest-hounds-sin.md new file mode 100644 index 00000000000..416b4640271 --- /dev/null +++ b/.changeset/honest-hounds-sin.md @@ -0,0 +1,5 @@ +--- +"@firebase/firestore": patch +--- + +Added new internal HTTP header to all network requests. diff --git a/packages/firestore/src/core/database_info.ts b/packages/firestore/src/core/database_info.ts index b9683f07731..a61b019b8bd 100644 --- a/packages/firestore/src/core/database_info.ts +++ b/packages/firestore/src/core/database_info.ts @@ -21,6 +21,7 @@ export class DatabaseInfo { * persistenceKey. * * @param databaseId - The database to use. + * @param appId - The Firebase App Id. * @param persistenceKey - A unique identifier for this Firestore's local * storage (used in conjunction with the databaseId). * @param host - The Firestore backend host to connect to. @@ -32,6 +33,7 @@ export class DatabaseInfo { */ constructor( readonly databaseId: DatabaseId, + readonly appId: string, readonly persistenceKey: string, readonly host: string, readonly ssl: boolean, diff --git a/packages/firestore/src/exp/database.ts b/packages/firestore/src/exp/database.ts index 58ea920065e..b0a6ac0f1d1 100644 --- a/packages/firestore/src/exp/database.ts +++ b/packages/firestore/src/exp/database.ts @@ -178,6 +178,7 @@ export function configureFirestore(firestore: FirebaseFirestore): void { const databaseInfo = makeDatabaseInfo( firestore._databaseId, + firestore._app?.options.appId || '', firestore._persistenceKey, settings ); diff --git a/packages/firestore/src/lite/components.ts b/packages/firestore/src/lite/components.ts index 3dee3d25400..3d896fa5fc0 100644 --- a/packages/firestore/src/lite/components.ts +++ b/packages/firestore/src/lite/components.ts @@ -70,6 +70,7 @@ export function getDatastore(firestore: FirestoreService): Datastore { logDebug(LOG_TAG, 'Initializing Datastore'); const databaseInfo = makeDatabaseInfo( firestore._databaseId, + firestore.app.options.appId || '', firestore._persistenceKey, firestore._freezeSettings() ); @@ -101,11 +102,13 @@ export function removeComponents(firestore: FirestoreService): void { export function makeDatabaseInfo( databaseId: DatabaseId, + appId: string, persistenceKey: string, settings: FirestoreSettings ): DatabaseInfo { return new DatabaseInfo( databaseId, + appId, persistenceKey, settings.host, settings.ssl, diff --git a/packages/firestore/src/lite/database.ts b/packages/firestore/src/lite/database.ts index 0ee13cd3ea4..e43e8742537 100644 --- a/packages/firestore/src/lite/database.ts +++ b/packages/firestore/src/lite/database.ts @@ -66,7 +66,7 @@ export class FirebaseFirestore implements FirestoreService { // all components have shut down. private _terminateTask?: Promise; - private _app?: FirebaseApp; + _app?: FirebaseApp; /** @hideconstructor */ constructor( diff --git a/packages/firestore/src/platform/node/grpc_connection.ts b/packages/firestore/src/platform/node/grpc_connection.ts index 24c84e611ad..1056c6694bf 100644 --- a/packages/firestore/src/platform/node/grpc_connection.ts +++ b/packages/firestore/src/platform/node/grpc_connection.ts @@ -38,7 +38,11 @@ import { Deferred } from '../../util/promise'; const LOG_TAG = 'Connection'; const X_GOOG_API_CLIENT_VALUE = `gl-node/${process.versions.node} fire/${SDK_VERSION} grpc/${grpcVersion}`; -function createMetadata(databasePath: string, token: Token | null): Metadata { +function createMetadata( + databasePath: string, + token: Token | null, + appId: string +): Metadata { hardAssert( token === null || token.type === 'OAuth', 'If provided, token must be OAuth' @@ -52,10 +56,11 @@ function createMetadata(databasePath: string, token: Token | null): Metadata { } } } - metadata.set('x-goog-api-client', X_GOOG_API_CLIENT_VALUE); + metadata.set('X-Firebase-GMPID', appId); + metadata.set('X-Goog-Api-Client', X_GOOG_API_CLIENT_VALUE); // This header is used to improve routing and project isolation by the // backend. - metadata.set('google-cloud-resource-prefix', databasePath); + metadata.set('Google-Cloud-Resource-Prefix', databasePath); return metadata; } @@ -102,7 +107,11 @@ export class GrpcConnection implements Connection { token: Token | null ): Promise { const stub = this.ensureActiveStub(); - const metadata = createMetadata(this.databasePath, token); + const metadata = createMetadata( + this.databasePath, + token, + this.databaseInfo.appId + ); const jsonRequest = { database: this.databasePath, ...request }; return nodePromise((callback: NodeCallback) => { @@ -147,7 +156,11 @@ export class GrpcConnection implements Connection { request ); const stub = this.ensureActiveStub(); - const metadata = createMetadata(this.databasePath, token); + const metadata = createMetadata( + this.databasePath, + token, + this.databaseInfo.appId + ); const jsonRequest = { ...request, database: this.databasePath }; const stream = stub[rpcName](jsonRequest, metadata); stream.on('data', (response: Resp) => { @@ -173,7 +186,11 @@ export class GrpcConnection implements Connection { token: Token | null ): Stream { const stub = this.ensureActiveStub(); - const metadata = createMetadata(this.databasePath, token); + const metadata = createMetadata( + this.databasePath, + token, + this.databaseInfo.appId + ); const grpcStream = stub[rpcName](metadata); let closed = false; diff --git a/packages/firestore/src/remote/rest_connection.ts b/packages/firestore/src/remote/rest_connection.ts index 535d4f33608..c52138e5fa2 100644 --- a/packages/firestore/src/remote/rest_connection.ts +++ b/packages/firestore/src/remote/rest_connection.ts @@ -119,6 +119,7 @@ export abstract class RestConnection implements Connection { token: Token | null ): void { headers['X-Goog-Api-Client'] = X_GOOG_API_CLIENT_VALUE; + headers['X-Firebase-GMPID'] = this.databaseInfo.appId; // Content-Type: text/plain will avoid preflight requests which might // mess with CORS and redirects by proxies. If we add custom headers diff --git a/packages/firestore/test/integration/util/internal_helpers.ts b/packages/firestore/test/integration/util/internal_helpers.ts index 9410bef925f..181b2a41bc7 100644 --- a/packages/firestore/test/integration/util/internal_helpers.ts +++ b/packages/firestore/test/integration/util/internal_helpers.ts @@ -43,6 +43,7 @@ export function asyncQueue(db: firestore.FirebaseFirestore): AsyncQueueImpl { export function getDefaultDatabaseInfo(): DatabaseInfo { return new DatabaseInfo( new DatabaseId(DEFAULT_PROJECT_ID), + 'test-app-id', 'persistenceKey', DEFAULT_SETTINGS.host!, !!DEFAULT_SETTINGS.ssl, diff --git a/packages/firestore/test/unit/local/persistence_test_helpers.ts b/packages/firestore/test/unit/local/persistence_test_helpers.ts index ae4fde7c3ae..2664899eecf 100644 --- a/packages/firestore/test/unit/local/persistence_test_helpers.ts +++ b/packages/firestore/test/unit/local/persistence_test_helpers.ts @@ -56,6 +56,7 @@ export const MOCK_SEQUENCE_NUMBER_SYNCER: SequenceNumberSyncer = { export const TEST_PROJECT = 'test-project'; export const TEST_DATABASE_ID = new DatabaseId(TEST_PROJECT); export const TEST_PERSISTENCE_KEY = '[PersistenceTestHelpers]'; +export const TEST_APP_ID = 'test-app-id'; /** The persistence prefix used for testing in IndexedBD and LocalStorage. */ export const TEST_PERSISTENCE_PREFIX = indexedDbStoragePrefix( diff --git a/packages/firestore/test/unit/remote/rest_connection.test.ts b/packages/firestore/test/unit/remote/rest_connection.test.ts index e8bbc8e83fa..93c2ccd4f38 100644 --- a/packages/firestore/test/unit/remote/rest_connection.test.ts +++ b/packages/firestore/test/unit/remote/rest_connection.test.ts @@ -58,6 +58,7 @@ export class TestRestConnection extends RestConnection { describe('RestConnection', () => { const testDatabaseInfo = new DatabaseInfo( new DatabaseId('testproject'), + 'test-app-id', 'persistenceKey', 'example.com', /*ssl=*/ false, @@ -92,6 +93,7 @@ describe('RestConnection', () => { expect(connection.lastHeaders).to.deep.equal({ 'Authorization': 'Bearer owner', 'Content-Type': 'text/plain', + 'X-Firebase-GMPID': 'test-app-id', 'X-Goog-Api-Client': `gl-js/ fire/${SDK_VERSION}` }); }); diff --git a/packages/firestore/test/unit/specs/spec_test_runner.ts b/packages/firestore/test/unit/specs/spec_test_runner.ts index abd05973c5d..a4eced7a962 100644 --- a/packages/firestore/test/unit/specs/spec_test_runner.ts +++ b/packages/firestore/test/unit/specs/spec_test_runner.ts @@ -143,6 +143,7 @@ import { import { clearTestPersistence, INDEXEDDB_TEST_DATABASE_NAME, + TEST_APP_ID, TEST_DATABASE_ID, TEST_PERSISTENCE_KEY, TEST_SERIALIZER @@ -246,6 +247,7 @@ abstract class TestRunner { this.clientId = `client${clientIndex}`; this.databaseInfo = new DatabaseInfo( TEST_DATABASE_ID, + TEST_APP_ID, TEST_PERSISTENCE_KEY, 'host', /*ssl=*/ false,