google / google/googleapis.dart

clientViaServiceAccount causes HttpException: Unexpected response (unsolicited response without request) from firestore.googleapis.com

Open
#376 2 comments 8 reactions 0 assignees View on GitHub
package:googleapis_auth
Dominant language
Dart
Stars
419
Forks
136
Avg merge
1h 21m
Merged PRs (30d)
5

Description

## Description

When using `clientViaServiceAccount` to make requests to `https://firestore.googleapis.com` there will occasionally be an `HttpException: Unexpected response (unsolicited response without request).`.

```
$ dart --version
Dart SDK version: 2.15.1 (stable) (Tue Dec 14 13:32:21 2021 +0100) on "macos_x64"
```

```
googleapis_auth:
dependency: "direct main"
description:
name: googleapis_auth
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
```

## Reproduction Steps

1. Run the following code with a valid service account json

```dart
import 'dart:async';
import 'dart:io';

import 'package:googleapis_auth/auth_io.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart';

Future main() async {
await runZonedGuarded(() async {
const scopes = ['https://www.googleapis.com/auth/datastore'];
const serviceAccountJson = ''; // TODO: update to a valid service account json
final serviceAccount = ServiceAccountCredentials.fromJson(
serviceAccountJson,
);
final client = await clientViaServiceAccount(serviceAccount, scopes);
final port = int.parse(Platform.environment['PORT'] ?? '8080');
final app = const Pipeline().addMiddleware(logRequests()).addHandler(
(request) async {
final uri = Uri.parse('https://firestore.googleapis.com');
final response = await client.get(uri);
return Response.ok(response.body);
},
);
final server = await serve(app, InternetAddress.anyIPv4, port);
print('Running at http://${server.address.host}:${server.port}');
}, (error, stackTrace) {
print(error);
print(stackTrace);
});
}
```

2. Make several consecutive requests to the local server `GET http://localhost:8080`
3. Observe the exception

```
Running at http://0.0.0.0:8080
2022-01-21T21:53:00.847696 0:00:00.202302 GET [200] /
2022-01-21T21:53:01.713517 0:00:00.051435 GET [200] /
2022-01-21T21:53:02.260907 0:00:00.033304 GET [200] /
2022-01-21T21:53:02.777838 0:00:00.036686 GET [200] /
2022-01-21T21:53:03.546246 0:00:00.036774 GET [200] /
HttpException: Unexpected response (unsolicited response without request).
#0 new _HttpClientConnection. (dart:_http/http_impl.dart:2052:9)
#1 _rootRunUnary (dart:async/zone.dart:1434:47)
#2 _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#3 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#4 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#5 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#6 _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:774:19)
#7 _StreamController._add (dart:async/stream_controller.dart:648:7)
#8 _StreamController.add (dart:async/stream_controller.dart:596:5)
#9 _HttpParser._headersEnd (dart:_http/http_parser.dart:403:17)
#10 _HttpParser._doParse (dart:_http/http_parser.dart:745:15)
#11 _HttpParser._parse (dart:_http/http_parser.dart:319:7)
#12 _HttpParser._onData (dart:_http/http_parser.dart:873:5)
#13 _rootRunUnary (dart:async/zone.dart:1434:47)
#14 _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#15 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#16 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#17 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#18 _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:774:19)
#19 _StreamController._add (dart:async/stream_controller.dart:648:7)
#20 _StreamController.add (dart:async/stream_controller.dart:596:5)
#21 _Socket._onData (dart:io-patch/socket_patch.dart:2314:41)
#22 _rootRunUnary (dart:async/zone.dart:1434:47)
#23 _CustomZone.runUnary (dart:async/zone.dart:1335:19)
#24 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1244:7)
#25 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:341:11)
#26 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
#27 _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:774:19)
#28 _StreamController._add (dart:async/stream_controller.dart:648:7)
#29 _StreamController.add (dart:async/stream_controller.dart:596:5)
#30 _RawSecureSocket._sendReadEvent (dart:io/secure_socket.dart:1000:19)
#31 _rootRun (dart:async/zone.dart:1418:47)
#32 _CustomZone.run (dart:async/zone.dart:1328:19)
#33 _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
#34 _CustomZone.bindCallbackGuarded. (dart:async/zone.dart:1276:23)
#35 _rootRun (dart:async/zone.dart:1426:13)
#36 _CustomZone.run (dart:async/zone.dart:1328:19)
#37 _CustomZone.bindCallback. (dart:async/zone.dart:1260:23)
#38 Timer._createTimer. (dart:async-patch/timer_patch.dart:18:15)
#39 _Timer._runTimers (dart:isolate-patch/timer_impl.dart:395:19)
#40 _Timer._handleMessage (dart:isolate-patch/timer_impl.dart:426:5)
#41 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:192:12)
```

If we use the standard `http.Client` from `package:http` this exception does not occur.

```dart
import 'dart:async';
import 'dart:io';

import 'package:http/http.dart' as http;
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart';

Future main() async {
await runZonedGuarded(() async {
final client = http.Client();
final port = int.parse(Platform.environment['PORT'] ?? '8080');
final app = const Pipeline().addMiddleware(logRequests()).addHandler(
(request) async {
final uri = Uri.parse('https://firestore.googleapis.com');
final response = await client.get(uri);
return Response.ok(response.body);
},
);
final server = await serve(app, InternetAddress.anyIPv4, port);
print('Running at http://${server.address.host}:${server.port}');
}, (error, stackTrace) {
print(error);
print(stackTrace);
});
}
```

Multiple Requests:

```
Running at http://0.0.0.0:8080
2022-01-21T21:58:13.651830 0:00:00.295129 GET [200] /
2022-01-21T21:58:14.273981 0:00:00.056287 GET [200] /
2022-01-21T21:58:14.866554 0:00:00.030461 GET [200] /
2022-01-21T21:58:15.317418 0:00:00.031419 GET [200] /
2022-01-21T21:58:15.782024 0:00:00.082221 GET [200] /
2022-01-21T21:58:16.309214 0:00:00.030496 GET [200] /
2022-01-21T21:58:16.688311 0:00:00.030222 GET [200] /
2022-01-21T21:58:17.039397 0:00:00.032393 GET [200] /
2022-01-21T21:58:17.371488 0:00:00.028748 GET [200] /
2022-01-21T21:58:19.100050 0:00:00.066094 GET [200] /
2022-01-21T21:58:19.607701 0:00:00.031278 GET [200] /
2022-01-21T21:58:21.145523 0:00:00.029277 GET [200] /
2022-01-21T21:58:21.506803 0:00:00.032348 GET [200] /
2022-01-21T21:58:21.943378 0:00:00.030565 GET [200] /
2022-01-21T21:58:22.472989 0:00:00.029346 GET [200] /
2022-01-21T21:58:22.833018 0:00:00.029295 GET [200] /
2022-01-21T21:58:23.159087 0:00:00.030631 GET [200] /
2022-01-21T21:58:23.529024 0:00:00.031687 GET [200] /
2022-01-21T21:58:23.883983 0:00:00.030004 GET [200] /
2022-01-21T21:58:24.232473 0:00:00.032988 GET [200] /
2022-01-21T21:58:24.580109 0:00:00.036904 GET [200] /
2022-01-21T21:58:24.894617 0:00:00.029898 GET [200] /
2022-01-21T21:58:25.217549 0:00:00.028578 GET [200] /
2022-01-21T21:58:25.548060 0:00:00.032187 GET [200] /
2022-01-21T21:58:25.881369 0:00:00.032185 GET [200] /
2022-01-21T21:58:26.200864 0:00:00.026827 GET [200] /
2022-01-21T21:58:26.520352 0:00:00.033838 GET [200] /
2022-01-21T21:58:26.828098 0:00:00.029993 GET [200] /
2022-01-21T21:58:28.275644 0:00:00.033963 GET [200] /
2022-01-21T21:58:28.686225 0:00:00.036012 GET [200] /
2022-01-21T21:58:29.000088 0:00:00.027196 GET [200] /
```

## Additional Context

![Screen Shot 2022-01-21 at 10 04 43 PM](https://user-images.githubusercontent.com/8855632/150624063-1bf02b4e-aaf6-4ef7-9291-0ceb34ac999e.png)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.