Skip to content

Commit 080a90d

Browse files
authored
Add Cookie Support For Firebase Studio (#8986)
1 parent 0e12766 commit 080a90d

File tree

9 files changed

+60
-6
lines changed

9 files changed

+60
-6
lines changed

common/api-review/util.api.md

+3
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,9 @@ export function ordinal(i: number): string;
398398
// @public (undocumented)
399399
export type PartialObserver<T> = Partial<Observer<T>>;
400400

401+
// @public
402+
export function pingServer(endpoint: string): Promise<boolean>;
403+
401404
// Warning: (ae-internal-missing-underscore) The name "promiseWithTimeout" should be prefixed with an underscore because the declaration is marked as @internal
402405
//
403406
// @internal

packages/auth/src/core/auth/emulator.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { Auth } from '../../model/public_types';
1818
import { AuthErrorCode } from '../errors';
1919
import { _assert } from '../util/assert';
2020
import { _castAuth } from './auth_impl';
21-
import { deepEqual } from '@firebase/util';
21+
import { deepEqual, isCloudWorkstation, pingServer } from '@firebase/util';
2222

2323
/**
2424
* Changes the {@link Auth} instance to communicate with the Firebase Auth Emulator, instead of production
@@ -100,6 +100,11 @@ export function connectAuthEmulator(
100100
if (!disableWarnings) {
101101
emitEmulatorWarning();
102102
}
103+
104+
// Workaround to get cookies in Firebase Studio
105+
if (isCloudWorkstation(host)) {
106+
void pingServer(`${protocol}//${host}:${port}`);
107+
}
103108
}
104109

105110
function extractProtocol(url: string): string {

packages/data-connect/src/api/DataConnect.ts

+5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
import { AppCheckInternalComponentName } from '@firebase/app-check-interop-types';
2525
import { FirebaseAuthInternalName } from '@firebase/auth-interop-types';
2626
import { Provider } from '@firebase/component';
27+
import { isCloudWorkstation, pingServer } from '@firebase/util';
2728

2829
import { AppCheckTokenProvider } from '../core/AppCheckTokenProvider';
2930
import { Code, DataConnectError } from '../core/error';
@@ -237,6 +238,10 @@ export function connectDataConnectEmulator(
237238
port?: number,
238239
sslEnabled = false
239240
): void {
241+
// Workaround to get cookies in Firebase Studio
242+
if (isCloudWorkstation(host)) {
243+
void pingServer(`https://${host}${port ? `:${port}` : ''}`);
244+
}
240245
dc.enableEmulator({ host, port, sslEnabled });
241246
}
242247

packages/database/src/api/Database.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ import {
3030
deepEqual,
3131
EmulatorMockTokenOptions,
3232
getDefaultEmulatorHostnameAndPort,
33-
isCloudWorkstation
33+
isCloudWorkstation,
34+
pingServer
3435
} from '@firebase/util';
3536

3637
import { AppCheckTokenProvider } from '../core/AppCheckTokenProvider';
@@ -389,6 +390,11 @@ export function connectDatabaseEmulator(
389390
tokenProvider = new EmulatorTokenProvider(token);
390391
}
391392

393+
// Workaround to get cookies in Firebase Studio
394+
if (isCloudWorkstation(host)) {
395+
void pingServer(host);
396+
}
397+
392398
// Modify the repo to apply emulator settings
393399
repoManagerApplyEmulatorSettings(repo, hostAndPort, options, tokenProvider);
394400
}

packages/firestore/src/api/database.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@ import {
2121
FirebaseApp,
2222
getApp
2323
} from '@firebase/app';
24-
import { deepEqual, getDefaultEmulatorHostnameAndPort } from '@firebase/util';
24+
import {
25+
deepEqual,
26+
getDefaultEmulatorHostnameAndPort,
27+
isCloudWorkstation,
28+
pingServer
29+
} from '@firebase/util';
2530

2631
import { User } from '../auth/user';
2732
import {
@@ -194,6 +199,11 @@ export function initializeFirestore(
194199
);
195200
}
196201

202+
// Workaround to get cookies in Firebase Studio
203+
if (settings.host && isCloudWorkstation(settings.host)) {
204+
void pingServer(settings.host);
205+
}
206+
197207
return provider.initialize({
198208
options: settings,
199209
instanceIdentifier: databaseId

packages/firestore/src/lite-api/database.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ import {
2727
deepEqual,
2828
EmulatorMockTokenOptions,
2929
getDefaultEmulatorHostnameAndPort,
30-
isCloudWorkstation
30+
isCloudWorkstation,
31+
pingServer
3132
} from '@firebase/util';
3233

3334
import {
@@ -333,6 +334,9 @@ export function connectFirestoreEmulator(
333334
emulatorOptions: firestore._getEmulatorOptions()
334335
};
335336
const newHostSetting = `${host}:${port}`;
337+
if (useSsl) {
338+
void pingServer(`https://${newHostSetting}`);
339+
}
336340
if (settings.host !== DEFAULT_HOST && settings.host !== newHostSetting) {
337341
logWarn(
338342
'Host has been set in both settings() and connectFirestoreEmulator(), emulator host ' +

packages/functions/src/service.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import { Provider } from '@firebase/component';
3030
import { FirebaseAuthInternalName } from '@firebase/auth-interop-types';
3131
import { MessagingInternalComponentName } from '@firebase/messaging-interop-types';
3232
import { AppCheckInternalComponentName } from '@firebase/app-check-interop-types';
33-
import { isCloudWorkstation } from '@firebase/util';
33+
import { isCloudWorkstation, pingServer } from '@firebase/util';
3434

3535
export const DEFAULT_REGION = 'us-central1';
3636

@@ -179,6 +179,10 @@ export function connectFunctionsEmulator(
179179
functionsInstance.emulatorOrigin = `http${
180180
useSsl ? 's' : ''
181181
}://${host}:${port}`;
182+
// Workaround to get cookies in Firebase Studio
183+
if (useSsl) {
184+
void pingServer(functionsInstance.emulatorOrigin);
185+
}
182186
}
183187

184188
/**

packages/storage/src/service.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ import { FirebaseStorage } from './public-types';
4545
import {
4646
createMockUserToken,
4747
EmulatorMockTokenOptions,
48-
isCloudWorkstation
48+
isCloudWorkstation,
49+
pingServer
4950
} from '@firebase/util';
5051
import { Connection, ConnectionType } from './implementation/connection';
5152

@@ -146,6 +147,10 @@ export function connectStorageEmulator(
146147
): void {
147148
storage.host = `${host}:${port}`;
148149
const useSsl = isCloudWorkstation(host);
150+
// Workaround to get cookies in Firebase Studio
151+
if (useSsl) {
152+
void pingServer(`https://${storage.host}`);
153+
}
149154
storage._isUsingEmulator = true;
150155
storage._protocol = useSsl ? 'https' : 'http';
151156
const { mockUserToken } = options;

packages/util/src/url.ts

+12
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,15 @@
2222
export function isCloudWorkstation(host: string): boolean {
2323
return host.endsWith('.cloudworkstations.dev');
2424
}
25+
26+
/**
27+
* Makes a fetch request to the given server.
28+
* Mostly used for forwarding cookies in Firebase Studio.
29+
* @public
30+
*/
31+
export async function pingServer(endpoint: string): Promise<boolean> {
32+
const result = await fetch(endpoint, {
33+
credentials: 'include'
34+
});
35+
return result.ok;
36+
}

0 commit comments

Comments
 (0)