blob: b2fd501ee162e6fa5b9a4f0aa6cb3a1259d888b8 [file] [log] [blame]
// Copyright 2019 The Flutter Authors. 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:io';
import 'dart:typed_data';
import 'package:appengine/appengine.dart';
import 'package:gcloud/db.dart';
import 'package:meta/meta.dart';
import '../datastore/cocoon_config.dart';
import '../model/appengine/key_helper.dart';
import '../model/appengine/log_chunk.dart';
import '../model/appengine/task.dart';
import '../request_handling/api_request_handler.dart';
import '../request_handling/authentication.dart';
import '../request_handling/body.dart';
import '../request_handling/exceptions.dart';
import '../service/datastore.dart';
/// Serves a log file to the user as a text file.
@immutable
class GetLog extends ApiRequestHandler<Body> {
const GetLog(
Config config,
AuthenticationProvider authenticationProvider, {
@visibleForTesting DatastoreServiceProvider datastoreProvider,
}) : datastoreProvider =
datastoreProvider ?? DatastoreService.defaultProvider,
super(config: config, authenticationProvider: authenticationProvider);
final DatastoreServiceProvider datastoreProvider;
static const String ownerKeyParam = 'ownerKey';
@override
Future<Body> get() async {
final String encodedOwnerKey = request.uri.queryParameters[ownerKeyParam];
if (encodedOwnerKey == null) {
throw const BadRequestException(
'Missing required query parameter: $ownerKeyParam');
}
final KeyHelper keyHelper =
KeyHelper(applicationContext: context.applicationContext);
final Key ownerKey = keyHelper.decode(encodedOwnerKey);
final DatastoreService datastore = datastoreProvider(config.db);
final Task task =
await datastore.db.lookupValue<Task>(ownerKey, orElse: () => null);
if (task == null) {
throw const BadRequestException(
'Invalid owner key. Owner entity does not exist.');
}
response.headers
.set(HttpHeaders.contentTypeHeader, 'text/html; charset=utf-8');
return Body.forStream(_getResponse(datastore, task, ownerKey));
}
Stream<Uint8List> _getResponse(
DatastoreService datastore, Task task, Key ownerKey) async* {
yield utf8.encode('\n\n------------ TASK ------------\n') as Uint8List;
yield utf8.encode(task.toString()) as Uint8List;
yield utf8.encode('\n\n------------ LOG ------------\n') as Uint8List;
final Query<LogChunk> query = datastore.db.query<LogChunk>()
..filter('ownerKey =', ownerKey)
..order('createTimestamp');
yield* query
.run()
.map<Uint8List>((LogChunk chunk) => chunk.data as Uint8List);
}
}