blob: 772b6aa509bbd64628639d6ad7417d9e9a23db1d [file] [log] [blame]
// 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:io';
import 'package:async/async.dart';
import 'package:dwds/data/extension_request.dart';
import 'package:dwds/src/events.dart';
import 'package:dwds/src/handlers/socket_connections.dart';
import 'package:dwds/src/servers/extension_debugger.dart';
import 'package:dwds/src/utilities/server.dart';
import 'package:logging/logging.dart';
import 'package:shelf/shelf.dart';
const authenticationResponse = 'Dart Debug Authentication Success!\n\n'
'You can close this tab and launch the Dart Debug Extension again.';
/// A backend for the Dart Debug Extension.
///
/// Sets up an SSE handler to communicate with the extension background.
/// Uses that SSE channel to create an [ExtensionDebugger].
class ExtensionBackend {
static final _logger = Logger('ExtensionBackend');
final String hostname;
final int port;
final HttpServer _server;
/// Null until [close] is called.
///
/// All subsequent calls to [close] will return this future.
Future<void>? _closed;
ExtensionBackend._(
SocketHandler socketHandler, this.hostname, this.port, this._server)
: connections = socketHandler.connections;
// Starts the backend on an open port.
static Future<ExtensionBackend> start(
SocketHandler socketHandler, String hostname) async {
var cascade = Cascade();
cascade = cascade.add((request) {
if (request.url.path == authenticationPath) {
return Response.ok(authenticationResponse, headers: {
if (request.headers.containsKey('origin'))
'Access-Control-Allow-Origin': request.headers['origin']!,
'Access-Control-Allow-Credentials': 'true'
});
}
return Response.notFound('');
}).add(socketHandler.handler);
final server = await startHttpServer(hostname);
serveHttpRequests(server, cascade.handler, (e, s) {
_logger.warning('Error serving requests', e);
emitEvent(DwdsEvent.httpRequestException('ExtensionBackend', '$e:$s'));
});
return ExtensionBackend._(
socketHandler, server.address.host, server.port, server);
}
Future<void> close() => _closed ??= _server.close();
final StreamQueue<SocketConnection> connections;
Future<ExtensionDebugger> get extensionDebugger async =>
ExtensionDebugger(await connections.next);
}