handler method

Future<Response> handler(
  1. 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.isNotEmpty);

  // Get the relative path

  final values = req.pathParams.values('*');
  if (values.isEmpty) {
    throw ArgumentError('Static file handler registered with no *');
  } else if (1 < values.length) {
    throw 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 NotFoundException(NotFoundException.foundStaticHandler);
        } else {
          throw NoResponseFromHandler();
        }
      }
    } 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 = File(path);
    if (file.existsSync()) {
      _logStaticFiles.finest('[${req.id}] static file found: $path');
      return await _serveFile(req, file);
    } else if (allowFilePathsAsDirectories && Directory(path).existsSync()) {
      // 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 to have a '/' at the end,
        // otherwise any relative links would break.
        _logStaticFiles.finest('[${req.id}] treating as static directory');

        // Determine the actual URL that was requested, taking into account
        // any proxying (indicated by [publicUrlPrefix]). If the proxying
        // is not taken into account, the browser won't be able to resolve
        // the URL in the redirect response.
        //
        // In the following, remember `req.requestPath()` is an internal URL
        // that always starts with '~/'.
        //
        // See [publicUrlPrefix] for details.

        String requestedUrl;
        if (publicServerUrl.isEmpty) {
          // No proxying
          requestedUrl = req.requestPath();
        } else if (publicServerUrl.endsWith('/')) {
          // Public URL prefix already ends in a slash, so don't use the
          // slash at the beginning of the requestPath when concatenating.
          requestedUrl = publicServerUrl + req.requestPath().substring(2);
        } else {
          // Public URL prefix does not end in a slash, so use the slash at
          // the beginning of the requestPath
          requestedUrl = publicServerUrl + req.requestPath().substring(1);
        }

        return ResponseRedirect('$requestedUrl/'); // append a slash
      }
    } else {
      _logStaticFiles.finest('[${req.id}] static file not found');
    }
  } else {
    // Request for a directory

    final dir = Directory(path);

    if (dir.existsSync()) {
      // 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 NotFoundException(NotFoundException.foundStaticHandler);
  } else {
    throw NoResponseFromHandler();
  }
}