Skip to content

Commit

Permalink
An attempt at conservative default cache-control headers (#7587)
Browse files Browse the repository at this point in the history
* An attempt at conservative default cache-control headers

* Reduce default cache-control max-age
  • Loading branch information
jonasfj authored Mar 25, 2024
1 parent f194393 commit b895f98
Show file tree
Hide file tree
Showing 9 changed files with 85 additions and 19 deletions.
11 changes: 11 additions & 0 deletions app/lib/frontend/handlers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'package:shelf_router/shelf_router.dart';
import '../shared/handlers.dart';
import '../shared/urls.dart';

import 'handlers/headers.dart';
import 'handlers/misc.dart';
import 'handlers/pubapi.dart';
import 'handlers/redirects.dart';
Expand Down Expand Up @@ -68,11 +69,21 @@ shelf.Handler createAppHandler() {

final rs = await pubApiHandler(request);
if (rs != Router.routeNotFound) {
if (rs.statusCode == 200 &&
request.method == 'GET' &&
!CacheHeaders.hasCacheHeader(rs.headers)) {
return rs.change(headers: CacheHeaders.defaultApi());
}
return rs;
}

final res = await pubSiteHandler(request);
if (res != Router.routeNotFound) {
if (rs.statusCode == 200 &&
request.method == 'GET' &&
!CacheHeaders.hasCacheHeader(rs.headers)) {
return rs.change(headers: CacheHeaders.defaultUI());
}
return res;
}

Expand Down
26 changes: 18 additions & 8 deletions app/lib/frontend/handlers/account.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import '../../shared/urls.dart' as urls;
import '../templates/admin.dart';
import '../templates/consent.dart';
import '../templates/misc.dart' show renderUnauthenticatedPage;
import 'headers.dart';

/// Handles requests for /authorized
shelf.Response authorizedHandler(_) => htmlResponse(renderAuthorizedPage());
Expand Down Expand Up @@ -55,10 +56,13 @@ Future<shelf.Response> startSignInHandler(shelf.Request request) async {
);
return redirectResponse(
oauth2Url.toString(),
headers: session_cookie.createClientSessionCookie(
sessionId: session.sessionId,
maxAge: session.maxAge,
),
headers: {
...session_cookie.createClientSessionCookie(
sessionId: session.sessionId,
maxAge: session.maxAge,
),
...CacheHeaders.privateZero(),
},
);
}

Expand Down Expand Up @@ -109,10 +113,13 @@ Future<shelf.Response> signInCompleteHandler(shelf.Request request) async {
);
return redirectResponse(
go,
headers: session_cookie.createClientSessionCookie(
sessionId: newSession.sessionId,
maxAge: newSession.maxAge,
),
headers: {
...session_cookie.createClientSessionCookie(
sessionId: newSession.sessionId,
maxAge: newSession.maxAge,
),
...CacheHeaders.privateZero(),
},
);
}

Expand Down Expand Up @@ -174,6 +181,9 @@ Future<shelf.Response> consentPageHandler(
// Consent pages have the consent ID in the URL. Browsers should not pass on
// this ID to the pages that are linked from the consent page.
noReferrer: true,
headers: {
...CacheHeaders.privateZero(),
},
);
}

Expand Down
26 changes: 23 additions & 3 deletions app/lib/frontend/handlers/headers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ class CacheHeaders {
'private'
else if (public)
'public'
else if (requestContext.isNotAuthenticated)
else if (requestContext.isNotAuthenticated &&
requestContext.uiCacheEnabled &&
requestContext.sessionData == null)
'public'
else
'private',
Expand All @@ -57,8 +59,26 @@ class CacheHeaders {
return headers.containsKey(HttpHeaders.cacheControlHeader);
}

/// Default private-only caching.
static final defaultPrivate = CacheHeaders._(Duration.zero, private: true);
/// Private-only max-age zero.
static final privateZero = CacheHeaders._(Duration.zero, private: true);

/// Default cache-control for public user-interface
static final defaultPublicUI = CacheHeaders._(
Duration(minutes: 10),
public: true,
);

/// Default cache-control for user-interface
static final defaultUI = CacheHeaders._(
Duration(minutes: 10),
// public / private is inferred from authentication + session header
);

/// Default cache-control for API responses
static final defaultApi = CacheHeaders._(
Duration(minutes: 10),
// public / private is inferred from authentication + session header
);

/// Everything under the /documentation/ endpoint.
static final dartdocAsset = CacheHeaders._(Duration(minutes: 15));
Expand Down
13 changes: 11 additions & 2 deletions app/lib/frontend/handlers/misc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,16 @@ Future<shelf.Response> securityPageHandler(shelf.Request request) async {
/// Handles requests for /readiness_check
Future<shelf.Response> readinessCheckHandler(shelf.Request request) async {
if (nameTracker.isReady) {
return htmlResponse('OK');
return htmlResponse(
'OK',
headers: CacheHeaders.privateZero(),
);
} else {
return htmlResponse('Service Unavailable', status: 503);
return htmlResponse(
'Service Unavailable',
status: 503,
headers: CacheHeaders.privateZero(),
);
}
}

Expand Down Expand Up @@ -182,6 +189,7 @@ Future<shelf.Response> staticsHandler(shelf.Request request) async {
acceptsGzipEncoding ? staticFile.gzippedBytes : staticFile.bytes;
final headers = <String, String>{
if (acceptsGzipEncoding) HttpHeaders.contentEncodingHeader: 'gzip',
'Vary': 'Accept-Encoding',
HttpHeaders.contentTypeHeader: staticFile.contentType,
HttpHeaders.contentLengthHeader: bytes.length.toString(),
HttpHeaders.lastModifiedHeader: formatHttpDate(staticFile.lastModified),
Expand Down Expand Up @@ -232,6 +240,7 @@ Future<shelf.Response> experimentalHandler(shelf.Request request) async {
value: flags.encodedAsCookie(),
maxAge: experimentalCookieDuration,
),
...CacheHeaders.privateZero(),
});
}

Expand Down
1 change: 1 addition & 0 deletions app/lib/frontend/handlers/package.dart
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ Future<shelf.Response> packageScoreLogTxtHandler(
body: log ?? 'no log',
headers: {
'content-type': 'text/plain;charset=UTF-8',
...CacheHeaders.defaultPublicUI(),
},
);
}
Expand Down
12 changes: 9 additions & 3 deletions app/lib/frontend/handlers/report.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import '../../shared/handlers.dart';
import '../../shared/utils.dart';
import '../request_context.dart';
import '../templates/report.dart';
import 'headers.dart';

/// Handles GET /report
Future<shelf.Response> reportPageHandler(shelf.Request request) async {
Expand All @@ -29,9 +30,14 @@ Future<shelf.Response> reportPageHandler(shelf.Request request) async {
return unauthenticatedRs;
}

return htmlResponse(renderReportPage(
sessionData: requestContext.sessionData,
));
return htmlResponse(
renderReportPage(
sessionData: requestContext.sessionData,
),
headers: {
...CacheHeaders.privateZero(),
},
);
}

/// Handles POST /api/report
Expand Down
6 changes: 5 additions & 1 deletion app/lib/frontend/handlers/routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import '../../shared/handlers.dart';
import 'account.dart';
import 'atom_feed.dart';
import 'documentation.dart';
import 'headers.dart';
import 'landing.dart';
import 'listing.dart';
import 'misc.dart';
Expand All @@ -35,7 +36,10 @@ class PubSiteService {
// ****

@Route.get('/liveness_check')
Future<Response> livenessCheck(Request request) async => htmlResponse('OK');
Future<Response> livenessCheck(Request request) async => htmlResponse(
'OK',
headers: CacheHeaders.privateZero(),
);

@Route.get('/readiness_check')
Future<Response> readinessCheck(Request request) async =>
Expand Down
2 changes: 1 addition & 1 deletion app/lib/shared/handler_helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ shelf.Handler _requestContextWrapper(shelf.Handler handler) {
if (!context.uiCacheEnabled && !CacheHeaders.hasCacheHeader(rs.headers)) {
// Indicates that the response is intended for a single user and must not
// be stored by a shared cache. A private cache may store the response.
rs = rs.change(headers: CacheHeaders.defaultPrivate());
rs = rs.change(headers: CacheHeaders.privateZero());
}
return rs;
};
Expand Down
7 changes: 6 additions & 1 deletion app/lib/task/handlers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,10 @@ Future<shelf.Response> handleTaskResource(
}

if (request.method.toUpperCase() == 'HEAD') {
return htmlResponse('');
return htmlResponse(
'',
headers: CacheHeaders.defaultPublicUI(),
);
}

final acceptsGzip = request.acceptsGzipEncoding();
Expand All @@ -185,6 +188,8 @@ Future<shelf.Response> handleTaskResource(
headers: {
'Content-Type': mime,
if (acceptsGzip) 'Content-Encoding': 'gzip',
'Vary': 'Accept-Encoding',
...CacheHeaders.defaultPublicUI(),
},
);
}

0 comments on commit b895f98

Please sign in to comment.