Skip to content

Commit 1df52ad

Browse files
committed
Add X-Firebase-AppId header to requests
1 parent dcfb3da commit 1df52ad

File tree

14 files changed

+89
-8
lines changed

14 files changed

+89
-8
lines changed

common/api-review/vertexai.api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,7 @@ export const enum VertexAIErrorCode {
817817
INVALID_CONTENT = "invalid-content",
818818
INVALID_SCHEMA = "invalid-schema",
819819
NO_API_KEY = "no-api-key",
820+
NO_APP_ID = "no-app-id",
820821
NO_MODEL = "no-model",
821822
NO_PROJECT_ID = "no-project-id",
822823
PARSE_FAILED = "parse-failed",

docs-devsite/vertexai.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ export declare const enum VertexAIErrorCode
545545
| INVALID\_CONTENT | <code>&quot;invalid-content&quot;</code> | An error associated with a Content object. |
546546
| INVALID\_SCHEMA | <code>&quot;invalid-schema&quot;</code> | An error due to invalid Schema input. |
547547
| NO\_API\_KEY | <code>&quot;no-api-key&quot;</code> | An error occurred due to a missing Firebase API key. |
548+
| NO\_APP\_ID | <code>&quot;no-app-id&quot;</code> | An error occured due to a missing app ID. |
548549
| NO\_MODEL | <code>&quot;no-model&quot;</code> | An error occurred due to a model name not being specified during initialization. |
549550
| NO\_PROJECT\_ID | <code>&quot;no-project-id&quot;</code> | An error occurred due to a missing project ID. |
550551
| PARSE\_FAILED | <code>&quot;parse-failed&quot;</code> | An error occurred while parsing. |

packages/vertexai/src/api.test.ts

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ const fakeVertexAI: VertexAI = {
2727
automaticDataCollectionEnabled: true,
2828
options: {
2929
apiKey: 'key',
30-
projectId: 'my-project'
30+
projectId: 'my-project',
31+
appId: 'my-appid'
3132
}
3233
},
3334
location: 'us-central1'
@@ -48,7 +49,7 @@ describe('Top level API', () => {
4849
it('getGenerativeModel throws if no apiKey is provided', () => {
4950
const fakeVertexNoApiKey = {
5051
...fakeVertexAI,
51-
app: { options: { projectId: 'my-project' } }
52+
app: { options: { projectId: 'my-project', appId: 'my-appid' } }
5253
} as VertexAI;
5354
try {
5455
getGenerativeModel(fakeVertexNoApiKey, { model: 'my-model' });
@@ -64,7 +65,7 @@ describe('Top level API', () => {
6465
it('getGenerativeModel throws if no projectId is provided', () => {
6566
const fakeVertexNoProject = {
6667
...fakeVertexAI,
67-
app: { options: { apiKey: 'my-key' } }
68+
app: { options: { apiKey: 'my-key', appId: 'my-appid' } }
6869
} as VertexAI;
6970
try {
7071
getGenerativeModel(fakeVertexNoProject, { model: 'my-model' });
@@ -79,6 +80,24 @@ describe('Top level API', () => {
7980
);
8081
}
8182
});
83+
it('getGenerativeModel throws if no appId is provided', () => {
84+
const fakeVertexNoProject = {
85+
...fakeVertexAI,
86+
app: { options: { apiKey: 'my-key' , projectId: 'my-projectid'} }
87+
} as VertexAI;
88+
try {
89+
getGenerativeModel(fakeVertexNoProject, { model: 'my-model' });
90+
} catch (e) {
91+
expect((e as VertexAIError).code).includes(
92+
VertexAIErrorCode.NO_APP_ID
93+
);
94+
expect((e as VertexAIError).message).equals(
95+
`VertexAI: The "appId" field is empty in the local` +
96+
` Firebase config. Firebase VertexAI requires this field ` +
97+
`to contain a valid app ID. (vertexAI/${VertexAIErrorCode.NO_APP_ID})`
98+
);
99+
}
100+
});
82101
it('getGenerativeModel gets a GenerativeModel', () => {
83102
const genModel = getGenerativeModel(fakeVertexAI, { model: 'my-model' });
84103
expect(genModel).to.be.an.instanceOf(GenerativeModel);
@@ -98,7 +117,7 @@ describe('Top level API', () => {
98117
it('getImagenModel throws if no apiKey is provided', () => {
99118
const fakeVertexNoApiKey = {
100119
...fakeVertexAI,
101-
app: { options: { projectId: 'my-project' } }
120+
app: { options: { projectId: 'my-project', appId: 'my-appid' } }
102121
} as VertexAI;
103122
try {
104123
getImagenModel(fakeVertexNoApiKey, { model: 'my-model' });
@@ -114,7 +133,7 @@ describe('Top level API', () => {
114133
it('getImagenModel throws if no projectId is provided', () => {
115134
const fakeVertexNoProject = {
116135
...fakeVertexAI,
117-
app: { options: { apiKey: 'my-key' } }
136+
app: { options: { apiKey: 'my-key', appId: 'my-appid' } }
118137
} as VertexAI;
119138
try {
120139
getImagenModel(fakeVertexNoProject, { model: 'my-model' });
@@ -129,6 +148,24 @@ describe('Top level API', () => {
129148
);
130149
}
131150
});
151+
it('getImagenModel throws if no appId is provided', () => {
152+
const fakeVertexNoProject = {
153+
...fakeVertexAI,
154+
app: { options: { apiKey: 'my-key', projectId: 'my-project' } }
155+
} as VertexAI;
156+
try {
157+
getImagenModel(fakeVertexNoProject, { model: 'my-model' });
158+
} catch (e) {
159+
expect((e as VertexAIError).code).includes(
160+
VertexAIErrorCode.NO_APP_ID
161+
);
162+
expect((e as VertexAIError).message).equals(
163+
`VertexAI: The "appId" field is empty in the local` +
164+
` Firebase config. Firebase VertexAI requires this field ` +
165+
`to contain a valid app ID. (vertexAI/${VertexAIErrorCode.NO_APP_ID})`
166+
);
167+
}
168+
});
132169
it('getImagenModel gets an ImagenModel', () => {
133170
const genModel = getImagenModel(fakeVertexAI, { model: 'my-model' });
134171
expect(genModel).to.be.an.instanceOf(ImagenModel);

packages/vertexai/src/methods/chat-session.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use(chaiAsPromised);
3030
const fakeApiSettings: ApiSettings = {
3131
apiKey: 'key',
3232
project: 'my-project',
33+
appId: 'my-appid',
3334
location: 'us-central1'
3435
};
3536

packages/vertexai/src/methods/count-tokens.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use(chaiAsPromised);
3232
const fakeApiSettings: ApiSettings = {
3333
apiKey: 'key',
3434
project: 'my-project',
35+
appId: 'my-appid',
3536
location: 'us-central1'
3637
};
3738

packages/vertexai/src/methods/generate-content.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ use(chaiAsPromised);
3737
const fakeApiSettings: ApiSettings = {
3838
apiKey: 'key',
3939
project: 'my-project',
40+
appId: 'my-appid',
4041
location: 'us-central1'
4142
};
4243

packages/vertexai/src/models/generative-model.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ const fakeVertexAI: VertexAI = {
3030
automaticDataCollectionEnabled: true,
3131
options: {
3232
apiKey: 'key',
33-
projectId: 'my-project'
33+
projectId: 'my-project',
34+
appId: 'my-appid'
3435
}
3536
},
3637
location: 'us-central1'

packages/vertexai/src/models/imagen-model.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ const fakeVertexAI: VertexAI = {
3737
automaticDataCollectionEnabled: true,
3838
options: {
3939
apiKey: 'key',
40-
projectId: 'my-project'
40+
projectId: 'my-project',
41+
appId: 'my-appid'
4142
}
4243
},
4344
location: 'us-central1'

packages/vertexai/src/models/vertexai-model.test.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ const fakeVertexAI: VertexAI = {
3838
automaticDataCollectionEnabled: true,
3939
options: {
4040
apiKey: 'key',
41-
projectId: 'my-project'
41+
projectId: 'my-project',
42+
appId: 'my-appid'
4243
}
4344
},
4445
location: 'us-central1'
@@ -100,4 +101,24 @@ describe('VertexAIModel', () => {
100101
);
101102
}
102103
});
104+
it('throws if not passed an app ID', () => {
105+
const fakeVertexAI: VertexAI = {
106+
app: {
107+
name: 'DEFAULT',
108+
automaticDataCollectionEnabled: true,
109+
options: {
110+
apiKey: 'key',
111+
projectId: 'my-project'
112+
}
113+
},
114+
location: 'us-central1'
115+
};
116+
try {
117+
new TestModel(fakeVertexAI, 'my-model');
118+
} catch (e) {
119+
expect((e as VertexAIError).code).to.equal(
120+
VertexAIErrorCode.NO_APP_ID
121+
);
122+
}
123+
});
103124
});

packages/vertexai/src/models/vertexai-model.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,16 @@ export abstract class VertexAIModel {
6868
VertexAIErrorCode.NO_PROJECT_ID,
6969
`The "projectId" field is empty in the local Firebase config. Firebase VertexAI requires this field to contain a valid project ID.`
7070
);
71+
} else if (!vertexAI.app?.options?.appId) {
72+
throw new VertexAIError(
73+
VertexAIErrorCode.NO_APP_ID,
74+
`The "appId" field is empty in the local Firebase config. Firebase VertexAI requires this field to contain a valid app ID.`
75+
);
7176
} else {
7277
this._apiSettings = {
7378
apiKey: vertexAI.app.options.apiKey,
7479
project: vertexAI.app.options.projectId,
80+
appId: vertexAI.app.options.appId,
7581
location: vertexAI.location
7682
};
7783

packages/vertexai/src/requests/request.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use(chaiAsPromised);
3232
const fakeApiSettings: ApiSettings = {
3333
apiKey: 'key',
3434
project: 'my-project',
35+
appId: 'my-appid',
3536
location: 'us-central1'
3637
};
3738

@@ -103,6 +104,7 @@ describe('request methods', () => {
103104
const fakeApiSettings: ApiSettings = {
104105
apiKey: 'key',
105106
project: 'myproject',
107+
appId: 'my-appid',
106108
location: 'moon',
107109
getAuthToken: () => Promise.resolve({ accessToken: 'authtoken' }),
108110
getAppCheckToken: () => Promise.resolve({ token: 'appchecktoken' })
@@ -135,6 +137,7 @@ describe('request methods', () => {
135137
{
136138
apiKey: 'key',
137139
project: 'myproject',
140+
appId: 'my-appid',
138141
location: 'moon'
139142
},
140143
true,
@@ -167,6 +170,7 @@ describe('request methods', () => {
167170
{
168171
apiKey: 'key',
169172
project: 'myproject',
173+
appId: 'my-appid',
170174
location: 'moon',
171175
getAppCheckToken: () =>
172176
Promise.resolve({ token: 'dummytoken', error: Error('oops') })
@@ -193,6 +197,7 @@ describe('request methods', () => {
193197
{
194198
apiKey: 'key',
195199
project: 'myproject',
200+
appId: 'my-appid',
196201
location: 'moon'
197202
},
198203
true,

packages/vertexai/src/requests/request.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ export async function getHeaders(url: RequestUrl): Promise<Headers> {
8484
headers.append('Content-Type', 'application/json');
8585
headers.append('x-goog-api-client', getClientHeaders());
8686
headers.append('x-goog-api-key', url.apiSettings.apiKey);
87+
headers.append('X-Firebase-AppId', url.apiSettings.appId); // Will be converted to 'X-Firebase-Appid' before it's sent in the browser.
8788
if (url.apiSettings.getAppCheckToken) {
8889
const appCheckToken = await url.apiSettings.getAppCheckToken();
8990
if (appCheckToken) {

packages/vertexai/src/types/error.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ export const enum VertexAIErrorCode {
8787
/** An error occurred due to a missing Firebase API key. */
8888
NO_API_KEY = 'no-api-key',
8989

90+
/** An error occured due to a missing app ID. */
91+
NO_APP_ID = 'no-app-id',
92+
9093
/** An error occurred due to a model name not being specified during initialization. */
9194
NO_MODEL = 'no-model',
9295

packages/vertexai/src/types/internal.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export * from './imagen/internal';
2323
export interface ApiSettings {
2424
apiKey: string;
2525
project: string;
26+
appId: string;
2627
location: string;
2728
getAuthToken?: () => Promise<FirebaseAuthTokenData | null>;
2829
getAppCheckToken?: () => Promise<AppCheckTokenResult>;

0 commit comments

Comments
 (0)