Skip to content

Commit 04b94ac

Browse files
authored
feat(sql_connect): add "X-Client-Platform" and "X-Client-Version" headers (#18484)
1 parent 2f942f2 commit 04b94ac

3 files changed

Lines changed: 80 additions & 2 deletions

File tree

packages/firebase_data_connect/firebase_data_connect/lib/src/network/rest_transport.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,9 @@ class RestTransport implements DataConnectTransport {
8585
'Content-Type': 'application/json',
8686
'Accept': 'application/json',
8787
'x-goog-api-client': getGoogApiVal(sdkType, packageVersion),
88-
'x-firebase-client': getFirebaseClientVal(packageVersion)
88+
'x-firebase-client': getFirebaseClientVal(packageVersion),
89+
'x-client-platform': 'flutter',
90+
'x-client-version': packageVersion,
8991
};
9092
String? appCheckToken;
9193
try {

packages/firebase_data_connect/firebase_data_connect/lib/src/network/websocket_transport.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,10 +192,16 @@ class WebSocketTransport implements DataConnectTransport {
192192

193193
bool get isConnected => _channel != null;
194194

195+
@visibleForTesting
196+
Map<String, String> buildHeaders(String? authToken, String? appCheckToken) =>
197+
_buildHeaders(authToken, appCheckToken);
198+
195199
Map<String, String> _buildHeaders(String? authToken, String? appCheckToken) {
196200
Map<String, String> headers = {
197201
'x-goog-api-client': getGoogApiVal(sdkType, packageVersion),
198-
'x-firebase-client': getFirebaseClientVal(packageVersion)
202+
'x-firebase-client': getFirebaseClientVal(packageVersion),
203+
'x-client-platform': 'flutter',
204+
'x-client-version': packageVersion
199205
};
200206
if (authToken != null) {
201207
headers['X-Firebase-Auth-Token'] = authToken;

packages/firebase_data_connect/firebase_data_connect/test/src/network/rest_transport_test.dart

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,76 @@ void main() {
276276
).called(1);
277277
});
278278

279+
test('invokeOperation should include x-client-platform headers', () async {
280+
final mockResponse = http.Response('{"data": {"key": "value"}}', 200);
281+
when(
282+
mockHttpClient.post(
283+
any,
284+
headers: anyNamed('headers'),
285+
body: anyNamed('body'),
286+
),
287+
).thenAnswer((_) async => mockResponse);
288+
289+
String deserializer(String data) => 'Deserialized Data';
290+
291+
await transport.invokeOperation(
292+
'testQuery',
293+
'executeQuery',
294+
deserializer,
295+
null,
296+
null,
297+
'authToken123',
298+
);
299+
300+
verify(
301+
mockHttpClient.post(
302+
any,
303+
headers: argThat(
304+
allOf(
305+
containsPair('x-client-platform', 'flutter'),
306+
),
307+
named: 'headers',
308+
),
309+
body: anyNamed('body'),
310+
),
311+
).called(1);
312+
});
313+
314+
test('invokeOperation should include x-client-version headers', () async {
315+
final mockResponse = http.Response('{"data": {"key": "value"}}', 200);
316+
when(
317+
mockHttpClient.post(
318+
any,
319+
headers: anyNamed('headers'),
320+
body: anyNamed('body'),
321+
),
322+
).thenAnswer((_) async => mockResponse);
323+
324+
String deserializer(String data) => 'Deserialized Data';
325+
326+
await transport.invokeOperation(
327+
'testQuery',
328+
'executeQuery',
329+
deserializer,
330+
null,
331+
null,
332+
'authToken123',
333+
);
334+
335+
verify(
336+
mockHttpClient.post(
337+
any,
338+
headers: argThat(
339+
allOf(
340+
containsPair('x-client-version', packageVersion),
341+
),
342+
named: 'headers',
343+
),
344+
body: anyNamed('body'),
345+
),
346+
).called(1);
347+
});
348+
279349
test(
280350
'regression #17290 - invokeOperation should correctly decode UTF-8 response with international characters',
281351
() async {

0 commit comments

Comments
 (0)