| // 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); |
| } |