[ VM / Service ] Fixed HTTP requests with params not working correctly when auth codes are enabled

Change-Id: Ia6dbab2c8e46cdd1fce659f55ee16f3ad98e5d6d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/101021
Reviewed-by: Ryan Macnak <rmacnak@google.com>
Commit-Queue: Ben Konyi <bkonyi@google.com>
diff --git a/runtime/bin/vmservice/server.dart b/runtime/bin/vmservice/server.dart
index a2f1747..b003c6a 100644
--- a/runtime/bin/vmservice/server.dart
+++ b/runtime/bin/vmservice/server.dart
@@ -359,7 +359,8 @@
     }
     // HTTP based service request.
     final client = new HttpRequestClient(request, _service);
-    final message = new Message.fromUri(client, Uri.parse(path));
+    final message = new Message.fromUri(
+        client, Uri(path: path, queryParameters: request.uri.queryParameters));
     client.onRequest(message); // exception free, no need to try catch
   }
 
diff --git a/runtime/observatory/tests/service/http_auth_get_isolate_rpc_test.dart b/runtime/observatory/tests/service/http_auth_get_isolate_rpc_test.dart
new file mode 100644
index 0000000..5b0b5f6
--- /dev/null
+++ b/runtime/observatory/tests/service/http_auth_get_isolate_rpc_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'http_get_isolate_rpc_common.dart';
+import 'test_helper.dart';
+
+main(args) {
+  runIsolateTests(args, tests,
+      testeeBefore: testeeBefore,
+      // the testee is responsible for starting the
+      // web server.
+      testeeControlsServer: true,
+      useAuthToken: true);
+}
diff --git a/runtime/observatory/tests/service/http_auth_get_vm_rpc_test.dart b/runtime/observatory/tests/service/http_auth_get_vm_rpc_test.dart
new file mode 100644
index 0000000..8eff61f
--- /dev/null
+++ b/runtime/observatory/tests/service/http_auth_get_vm_rpc_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'http_get_vm_rpc_common.dart';
+import 'test_helper.dart';
+
+main(args) {
+  runIsolateTests(args, tests,
+      testeeBefore: testeeBefore,
+      // the testee is responsible for starting the
+      // web server.
+      testeeControlsServer: true,
+      useAuthToken: true);
+}
diff --git a/runtime/observatory/tests/service/http_get_isolate_rpc_common.dart b/runtime/observatory/tests/service/http_get_isolate_rpc_common.dart
new file mode 100644
index 0000000..30a0112
--- /dev/null
+++ b/runtime/observatory/tests/service/http_get_isolate_rpc_common.dart
@@ -0,0 +1,91 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:developer';
+import 'dart:io' as io;
+import 'package:observatory/service_io.dart' as S;
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+
+Future<String> getIsolateId(io.HttpClient httpClient, Uri serverUri) async {
+  // Build the request.
+  final pathSegments = <String>[]..addAll(serverUri.pathSegments);
+  String method = 'getVM';
+  if (pathSegments.isNotEmpty) {
+    pathSegments[pathSegments.length - 1] = method;
+  } else {
+    pathSegments.add(method);
+  }
+  final requestUri = serverUri.replace(pathSegments: pathSegments);
+  var request = await httpClient.getUrl(requestUri);
+  Map response = await (await request.close())
+      .transform(utf8.decoder)
+      .transform(json.decoder)
+      .first;
+  Map result = response['result'];
+  return result['isolates'][0]['id'];
+}
+
+Future<Null> testeeBefore() async {
+  print('testee before');
+  print(await Service.getInfo());
+  // Start the web server.
+  ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
+  expect(info.serverUri, isNotNull);
+  var httpClient = new io.HttpClient();
+
+  // Build the request.
+  final params = <String, String>{
+    'isolateId': await getIsolateId(httpClient, info.serverUri),
+  };
+
+  String method = 'getIsolate';
+  final pathSegments = <String>[]..addAll(info.serverUri.pathSegments);
+  if (pathSegments.isNotEmpty) {
+    pathSegments[pathSegments.length - 1] = method;
+  } else {
+    pathSegments.add(method);
+  }
+  final requestUri = info.serverUri
+      .replace(pathSegments: pathSegments, queryParameters: params);
+
+  try {
+    var request = await httpClient.getUrl(requestUri);
+    Map response = await (await request.close())
+        .transform(utf8.decoder)
+        .transform(json.decoder)
+        .first;
+    Map result = response['result'];
+    expect(result['type'], equals('Isolate'));
+    expect(result['id'], startsWith('isolates/'));
+    expect(result['number'], new isInstanceOf<String>());
+    expect(result['_originNumber'], equals(result['number']));
+    expect(result['startTime'], isPositive);
+    expect(result['livePorts'], isPositive);
+    expect(result['pauseOnExit'], isFalse);
+    expect(result['pauseEvent']['type'], equals('Event'));
+    expect(result['error'], isNull);
+    expect(result['_numZoneHandles'], isPositive);
+    expect(result['_numScopedHandles'], isPositive);
+    expect(result['rootLib']['type'], equals('@Library'));
+    expect(result['libraries'].length, isPositive);
+    expect(result['libraries'][0]['type'], equals('@Library'));
+    expect(result['breakpoints'].length, isZero);
+    expect(result['_heaps']['new']['type'], equals('HeapSpace'));
+    expect(result['_heaps']['old']['type'], equals('HeapSpace'));
+  } catch (e) {
+    fail('invalid request: $e');
+  }
+}
+
+var tests = <IsolateTest>[
+  (S.Isolate isolate) async {
+    await isolate.reload();
+    // Just getting here means that the testee enabled the service protocol
+    // web server.
+    expect(true, true);
+  }
+];
diff --git a/runtime/observatory/tests/service/http_get_isolate_rpc_test.dart b/runtime/observatory/tests/service/http_get_isolate_rpc_test.dart
new file mode 100644
index 0000000..261fa26
--- /dev/null
+++ b/runtime/observatory/tests/service/http_get_isolate_rpc_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'http_get_isolate_rpc_common.dart';
+import 'test_helper.dart';
+
+main(args) {
+  runIsolateTests(args, tests,
+      testeeBefore: testeeBefore,
+      // the testee is responsible for starting the
+      // web server.
+      testeeControlsServer: true);
+}
diff --git a/runtime/observatory/tests/service/http_get_vm_rpc_common.dart b/runtime/observatory/tests/service/http_get_vm_rpc_common.dart
new file mode 100644
index 0000000..b193dc9
--- /dev/null
+++ b/runtime/observatory/tests/service/http_get_vm_rpc_common.dart
@@ -0,0 +1,60 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:developer';
+import 'dart:io' as io;
+import 'package:observatory/service_io.dart' as S;
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+
+Future<Null> testeeBefore() async {
+  print('testee before');
+  print(await Service.getInfo());
+  // Start the web server.
+  ServiceProtocolInfo info = await Service.controlWebServer(enable: true);
+  expect(info.serverUri, isNotNull);
+  var httpClient = new io.HttpClient();
+
+  // Build the request.
+  final pathSegments = <String>[]..addAll(info.serverUri.pathSegments);
+  String method = 'getVM';
+  if (pathSegments.isNotEmpty) {
+    pathSegments[pathSegments.length - 1] = method;
+  } else {
+    pathSegments.add(method);
+  }
+  final requestUri = info.serverUri.replace(pathSegments: pathSegments);
+
+  try {
+    var request = await httpClient.getUrl(requestUri);
+    Map response = await (await request.close())
+        .transform(utf8.decoder)
+        .transform(json.decoder)
+        .first;
+    Map result = response['result'];
+    expect(result['type'], equals('VM'));
+    expect(result['name'], equals('vm'));
+    expect(result['architectureBits'], isPositive);
+    expect(result['targetCPU'], new isInstanceOf<String>());
+    expect(result['hostCPU'], new isInstanceOf<String>());
+    expect(result['version'], new isInstanceOf<String>());
+    expect(result['pid'], new isInstanceOf<int>());
+    expect(result['startTime'], isPositive);
+    expect(result['isolates'].length, isPositive);
+    expect(result['isolates'][0]['type'], equals('@Isolate'));
+  } catch (e) {
+    fail('invalid request: $e');
+  }
+}
+
+var tests = <IsolateTest>[
+  (S.Isolate isolate) async {
+    await isolate.reload();
+    // Just getting here means that the testee enabled the service protocol
+    // web server.
+    expect(true, true);
+  }
+];
diff --git a/runtime/observatory/tests/service/http_get_vm_rpc_test.dart b/runtime/observatory/tests/service/http_get_vm_rpc_test.dart
new file mode 100644
index 0000000..5484c5e
--- /dev/null
+++ b/runtime/observatory/tests/service/http_get_vm_rpc_test.dart
@@ -0,0 +1,14 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'http_get_vm_rpc_common.dart';
+import 'test_helper.dart';
+
+main(args) {
+  runIsolateTests(args, tests,
+      testeeBefore: testeeBefore,
+      // the testee is responsible for starting the
+      // web server.
+      testeeControlsServer: true);
+}