Skip to content

Commit 2e80d2f

Browse files
authored
Display better 404 messages when generated dartdoc page is missing. (#8038)
1 parent 25c0f6f commit 2e80d2f

File tree

4 files changed

+58
-12
lines changed

4 files changed

+58
-12
lines changed

app/lib/dartdoc/models.dart

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import 'package:json_annotation/json_annotation.dart';
77
part 'models.g.dart';
88

99
/// Describes the resolved version and the URL redirect info.
10-
@JsonSerializable()
10+
@JsonSerializable(includeIfNull: false)
1111
class ResolvedDocUrlVersion {
1212
/// The version to use to display the documentation.
1313
final String version;
@@ -20,13 +20,18 @@ class ResolvedDocUrlVersion {
2020
/// * `""` (indicating empty response)
2121
final String urlSegment;
2222

23+
/// When the resolution is empty, the 404 response will have this message.
24+
final String? message;
25+
2326
ResolvedDocUrlVersion({
2427
required this.version,
2528
required this.urlSegment,
29+
this.message,
2630
});
2731

28-
ResolvedDocUrlVersion.empty()
29-
: version = '',
32+
ResolvedDocUrlVersion.empty({
33+
required this.message,
34+
}) : version = '',
3035
urlSegment = '';
3136

3237
factory ResolvedDocUrlVersion.fromJson(Map<String, dynamic> json) =>
@@ -35,4 +40,5 @@ class ResolvedDocUrlVersion {
3540
Map<String, dynamic> toJson() => _$ResolvedDocUrlVersionToJson(this);
3641

3742
bool get isEmpty => version.isEmpty || urlSegment.isEmpty;
43+
bool get isLatestStable => urlSegment == 'latest';
3844
}

app/lib/dartdoc/models.g.dart

Lines changed: 16 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/lib/frontend/handlers/documentation.dart

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,10 @@ Future<shelf.Response> documentationHandler(shelf.Request request) async {
5050
final version = docFilePath.version!;
5151
final resolved = await _resolveDocUrlVersion(package, version);
5252
if (resolved.isEmpty) {
53-
return notFoundHandler(request);
53+
return notFoundHandler(
54+
request,
55+
body: resolved.message ?? default404NotFound,
56+
);
5457
}
5558
if (version != resolved.urlSegment) {
5659
return redirectResponse(pkgDocUrl(
@@ -147,7 +150,8 @@ Future<ResolvedDocUrlVersion> _resolveDocUrlVersion(
147150
if (version == 'latest') {
148151
final latestFinished = await taskBackend.latestFinishedVersion(package);
149152
if (latestFinished == null) {
150-
return ResolvedDocUrlVersion.empty();
153+
return ResolvedDocUrlVersion.empty(
154+
message: 'Analysis has not started yet.');
151155
}
152156
final latestVersion = await packageBackend.getLatestVersion(package);
153157
return ResolvedDocUrlVersion(
@@ -159,7 +163,7 @@ Future<ResolvedDocUrlVersion> _resolveDocUrlVersion(
159163
// Do not resolve if package version does not exists.
160164
final pv = await packageBackend.lookupPackageVersion(package, version);
161165
if (pv == null) {
162-
return ResolvedDocUrlVersion.empty();
166+
return ResolvedDocUrlVersion.empty(message: 'Not found.');
163167
}
164168

165169
// Select the closest version (may be the same as version) that has a finished analysis.

app/lib/task/handlers.dart

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:pub_dev/shared/handlers.dart';
99
import 'package:pub_dev/shared/redis_cache.dart';
1010
import 'package:pub_dev/shared/urls.dart';
1111
import 'package:pub_dev/task/backend.dart';
12+
import 'package:pub_dev/task/models.dart';
1213
import 'package:shelf/shelf.dart' as shelf;
1314

1415
const _safeMimeTypes = {
@@ -111,7 +112,31 @@ Future<shelf.Response> handleDartDoc(
111112
});
112113
// We use empty string to indicate missing file or bug in the file
113114
if (htmlBytes == null || htmlBytes.isEmpty) {
114-
return notFoundHandler(request);
115+
final status = await taskBackend.packageStatus(package);
116+
final vs = status.versions[version];
117+
if (vs == null) {
118+
return notFoundHandler(
119+
request,
120+
body: resolvedDocUrlVersion.isLatestStable
121+
? 'Analysis has not started yet.'
122+
: 'Version not selected for analysis.',
123+
);
124+
}
125+
String? message;
126+
switch (vs.status) {
127+
case PackageVersionStatus.pending:
128+
case PackageVersionStatus.running:
129+
message = 'Analysis has not finished yet.';
130+
break;
131+
case PackageVersionStatus.failed:
132+
message =
133+
'Analysis has failed, no `dartdoc` output has been generated.';
134+
break;
135+
case PackageVersionStatus.completed:
136+
message = '`dartdoc` did not generate this page.';
137+
break;
138+
}
139+
return notFoundHandler(request, body: message);
115140
}
116141
return htmlBytesResponse(htmlBytes);
117142
}

0 commit comments

Comments
 (0)