blob: 18edda6df5f69989f8f246c85edba41478f38793 [file] [log] [blame]
// Copyright (c) 2020, 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:convert';
import 'dart:io';
import 'package:dwds/src/readers/asset_reader.dart';
import 'package:http/http.dart' as http;
import 'package:http/io_client.dart';
import 'package:logging/logging.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf_proxy/shelf_proxy.dart';
/// A reader for resources provided by a proxy server.
class ProxyServerAssetReader implements AssetReader {
final _logger = Logger('ProxyServerAssetReader');
late final Handler _handler;
late final http.Client _client;
ProxyServerAssetReader(int assetServerPort,
{String root = '', String host = 'localhost', bool isHttps = false}) {
final scheme = isHttps ? 'https://' : 'http://';
final inner = HttpClient()
..maxConnectionsPerHost = 200
..idleTimeout = const Duration(seconds: 30)
..connectionTimeout = const Duration(seconds: 30);
_client = isHttps
? IOClient(inner..badCertificateCallback = (cert, host, port) => true)
: IOClient(inner);
var url = '$scheme$host:$assetServerPort/';
if (root.isNotEmpty) url += '$root/';
_handler = proxyHandler(url, client: _client);
}
@override
Future<String?> dartSourceContents(String serverPath) =>
_readResource(serverPath);
@override
Future<String?> sourceMapContents(String serverPath) =>
_readResource(serverPath);
Future<String?> _readResource(String path) async {
// Handlers expect a fully formed HTML URI. The actual hostname and port
// does not matter.
final response =
await _handler(Request('GET', Uri.parse('http://foo:0000/$path')));
if (response.statusCode != HttpStatus.ok) {
_logger.warning('''
Failed to load asset at path: $path.
Status code: ${response.statusCode}
Headers:
${const JsonEncoder.withIndent(' ').convert(response.headers)}
''');
return null;
} else {
return await response.readAsString();
}
}
@override
Future<String?> metadataContents(String serverPath) =>
_readResource(serverPath);
@override
Future<void> close() async => _client.close();
}