blob: 563e66cc5a83ee95c59c4f9b9051204f725cb38e [file] [log] [blame]
// Copyright (c) 2016, 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 'package:package_resolver/package_resolver.dart';
import 'package:path/path.dart' as p;
import 'package:shelf/shelf.dart';
import 'package:shelf_static/shelf_static.dart';
import 'async_handler.dart';
/// A shelf handler that serves a virtual packages directory based on a package
/// config.
class PackageConfigHandler {
/// The static handlers for serving entries in the package config, indexed by
/// name.
final _packageHandlers = <String, Handler>{};
/// The information specifying how to do package resolution.
final PackageResolver _resolver;
PackageConfigHandler(this._resolver);
/// The callback for handling a single request.
FutureOr<Response> call(Request request) {
var segments = request.url.pathSegments;
return _handlerFor(segments.first)(request.change(path: segments.first));
}
/// Creates a handler for [package] based on the package map in [_resolver].
Handler _handlerFor(String package) {
return _packageHandlers.putIfAbsent(package, () {
return AsyncHandler(_resolver.urlFor(package).then((url) {
var handler = url == null
? (_) => Response.notFound('Package $package not found.')
: createStaticHandler(p.fromUri(url), serveFilesOutsidePath: true);
return handler;
}));
});
}
}