Future documentationHandler()

in app/lib/frontend/handlers/documentation.dart [26:110]


Future<shelf.Response> documentationHandler(shelf.Request request) async {
  final docFilePath = parseRequestUri(request.requestedUri);
  if (docFilePath == null) {
    return notFoundHandler(request);
  }
  checkPackageVersionParams(docFilePath.package, docFilePath.version);
  if (redirectPackageUrls.containsKey(docFilePath.package)) {
    return redirectResponse(redirectPackageUrls[docFilePath.package]!);
  }
  if (!await packageBackend.isPackageVisible(docFilePath.package)) {
    return notFoundHandler(request);
  }
  if (docFilePath.version == null) {
    return redirectResponse(pkgDocUrl(docFilePath.package, isLatest: true));
  }
  if (docFilePath.path == null) {
    return redirectResponse('${request.requestedUri}/');
  }
  final String requestMethod = request.method.toUpperCase();
  final entry =
      await dartdocBackend.getEntry(docFilePath.package, docFilePath.version!);
  if (entry == null) {
    return notFoundHandler(request);
  }
  if (entry.isLatest == true && docFilePath.version != 'latest') {
    final version = await packageBackend.getLatestVersion(entry.packageName);
    if (version == docFilePath.version) {
      return redirectResponse(pkgDocUrl(docFilePath.package,
          isLatest: true, relativePath: docFilePath.path));
    }
  }
  if (requestMethod == 'HEAD') {
    if (!entry.hasContent && docFilePath.path!.endsWith('.html')) {
      return notFoundHandler(request);
    }
    final info = await dartdocBackend.getFileInfo(entry, docFilePath.path!);
    if (info == null) {
      return notFoundHandler(request);
    }
    // TODO: add content-length header too
    return htmlResponse('');
  }
  if (requestMethod == 'GET') {
    if (!entry.hasContent && docFilePath.path!.endsWith('.html')) {
      final logTxtUrl = pkgDocUrl(docFilePath.package,
          version: docFilePath.version, relativePath: 'log.txt');
      final versionsUrl = pkgVersionsUrl(docFilePath.package);
      final content = renderErrorPage(
          'Documentation missing',
          'Pub site failed to generate dartdoc for this package.\n\n'
              '- View [dartdoc log]($logTxtUrl)\n'
              '- Check [other versions]($versionsUrl) of the same package.\n');
      return htmlResponse(content, status: 404);
    }
    final info = await dartdocBackend.getFileInfo(entry, docFilePath.path!);
    if (info == null) {
      return notFoundHandler(request);
    }
    if (isNotModified(request, info.lastModified, info.etag)) {
      return shelf.Response.notModified();
    }
    final headers = {
      HttpHeaders.contentTypeHeader: contentType(docFilePath.path!),
      HttpHeaders.cacheControlHeader:
          'private, max-age=${staticShortCache.inSeconds}',
      HttpHeaders.lastModifiedHeader: formatHttpDate(info.lastModified),
      HttpHeaders.etagHeader: info.etag,
    };
    if (info.blobId != null) {
      final sendGzip = request.acceptsEncoding('gzip');
      final content = dartdocBackend.readFromBlob(entry, info);
      return shelf.Response(
        HttpStatus.ok,
        body: sendGzip ? content : content.transform(gzip.decoder),
        headers: {
          ...headers,
          if (sendGzip) HttpHeaders.contentEncodingHeader: 'gzip',
        },
      );
    }
    final stream = dartdocBackend.readContent(entry, docFilePath.path!);
    return shelf.Response(HttpStatus.ok, body: stream, headers: headers);
  }
  return notFoundHandler(request);
}