etag function

Middleware etag({
  1. bool weak = false,
})

ETag middleware for dynamic responses (handlers, not static files — darto_static already handles ETag for files).

After the handler runs it hashes the response body, sets the ETag header, and short-circuits to 304 Not Modified when the client's If-None-Match matches. Applies to GET/HEAD responses with status 200 and a body.

import 'package:darto/etag.dart';

app.use(etag());

app.get('/data', [], (c) => c.json({'hello': 'world'}));
// → ETag: "<sha1>"; a matching If-None-Match returns 304.

Pass weak to emit a weak validator (W/"…").

Implementation

Middleware etag({bool weak = false}) {
  return (Context c, Next next) async {
    await next();

    final r = c.response;
    if (r == null || r.alreadySent || r.statusCode != 200) return;

    final method = c.req.method.toUpperCase();
    if (method != 'GET' && method != 'HEAD') return;

    final bytes = r.bodyBytes();
    if (bytes.isEmpty) return;

    final hash = sha1.convert(bytes).toString();
    final tag = weak ? 'W/"$hash"' : '"$hash"';

    final ifNoneMatch = c.req.header('if-none-match');
    if (ifNoneMatch != null && _matches(ifNoneMatch, tag, hash)) {
      c.respond(const Response.empty(status: 304).withHeader('ETag', tag));
      return;
    }

    c.respond(r.withHeader('ETag', tag));
  };
}