handler method

Future<Response> handler (Request req)

Request handler.

Register this request handler with the server's pipeline using a pattern with a single wildcard pattern. That path parameter will be used as the relative path underneath the baseDir to find the file or directory.

Implementation

Future<Response> handler(Request req) async {
  assert(_baseDir != null);
  assert(_baseDir.isNotEmpty);

  // Get the relative path

  final values = req.pathParams.values("*");
  if (values.isEmpty) {
    throw new ArgumentError("Static file handler registered with no *");
  } else if (1 < values.length) {
    throw new ArgumentError("Static file handler registered with multiple *");
  }

  final components = values[0].split("/");
  var depth = 0;
  while (0 <= depth && depth < components.length) {
    final c = components[depth];
    if (c == "..") {
      components.removeAt(depth);
      depth--;
      if (depth < 0) {
        if (throwNotFoundExceptions) {
          // tried to climb above base directory
          throw new NotFoundException(NotFoundException.foundStaticHandler);
        } else {
          return null;
        }
      }
    } else if (c == ".") {
      components.removeAt(depth);
    } else if (c.isEmpty && depth != components.length - 1) {
      components.removeAt(depth); // keep last "" to indicate dir listing
    } else {
      depth++;
    }
  }

  final path = "$_baseDir/${components.join("/")}";
  _logStaticFiles.finer("[${req.id}] static file/directory requested: $path");

  if (!path.endsWith("/")) {
    // Probably a file

    final file = new File(path);
    if (file.existsSync()) {
      _logStaticFiles.finest("[${req.id}] static file found: $path");
      return await _serveFile(req, file);
    } else if (allowFilePathsAsDirectories &&
        await new Directory(path).exists()) {
      // A directory exists with the same name

      if (allowDirectoryListing || await _findDefaultFile("$path/") != null) {
        // Can tell the browser to treat it as a directory
        // Note: must change URL in browser, otherwise relative links break
        _logStaticFiles.finest("[${req.id}] treating as static directory");
        return new ResponseRedirect("${req.requestPath}/");
      }
    } else {
      _logStaticFiles.finest("[${req.id}] static file not found");
    }
  } else {
    // Request for a directory

    final dir = new Directory(path);

    if (await dir.exists()) {
      // Try to find one of the default files in that directory

      final defaultFile = await _findDefaultFile(path);

      if (defaultFile != null) {
        _logStaticFiles.finest(
            "[${req.id}] static directory: default file found: $defaultFile");
        return await _serveFile(req, defaultFile);
      }

      if (allowDirectoryListing) {
        // List the contents of the directory
        _logStaticFiles.finest("[${req.id}] returning directory listing");
        final notTop = (1 < components.length);
        return await directoryListing(req, dir, linkToParent: notTop);
      } else {
        _logStaticFiles
            .finest("[${req.id}] static directory listing not allowed");
      }
    } else {
      _logStaticFiles.finest("[${req.id}] static directory not found");
    }
  }

  // Not found (or directory listing not allowed)

  if (throwNotFoundExceptions) {
    throw new NotFoundException(NotFoundException.foundStaticHandler);
  } else {
    return null;
  }
}