← tests

etag

The framework's own conditional-request machinery: the validator it computes over the body, and the 304 it answers.

Comparable across every framework at one body size. Not across sizes: the small row hashes a row and the large row hashes fourteen hundred, and the ratio between them is a hash rate.

testheftrequestbasewhat differs from the base
etag.large4GET /etag/largejson.largethe framework hashing the body and writing the ETag it computed onto the response
etag.match_large4GET /etag/largeetag.largea conditional request answered 304, with no body
etag.stale_large4GET /etag/largeetag.largea conditional request whose validator does not match, answered in full
etag.small1GET /etag/smalljson.smallthe framework hashing the body and writing the ETag it computed onto the response

etag.large

heft 4

base json.largebase of etag.match_large, etag.stale_large

The framework hashing the body it is about to send and writing the validator it computed onto the response. Read against json.large, the difference is the hash and the header. The tag is the framework's own, so no two of them agree on it.

Request

GET /etag/large

No body.

Expected response

HTTP 200
etagis present
x-rb-serialis new, so the handler ran

payload items.large

{"size":"large","count":1425,"items":[{"id":1,"name":"slate-lamp-6647","category":"tools","priceCents":18928,"inStock":true},{"id":2,"name":"brass-hinge-5716","category":"garden","priceCents":17577,"inStock":true},{"id":3,"name":"linen-ring-6971","category":"kitchen","priceCents":5540,"inStock":true},{"id":4,"name":"copper-bolt-9217","category":"outdoor","priceCents":11562,"inStock":true},{"id":5,"name":"linen-lamp-8288","category":"office","priceCents":1413,"inStock":true},{"id":6,"name":"copper-pan-9308","category":"tools","priceCents":10795,"inStock":true},{"id":7,"name":"slate-seed-3051","category":"garden","priceCents":9667,"inStock":false},{"id":8,"name":"oak-lamp-8662","category":"kit
… 128,510 bytes total

Compared as parsed JSON, so key order and how a number is written do not matter.

Test source, tests/etag/large.ts
tests/etag/large.tsopen on GitHub →
import { performanceTest } from "#kit";
import { items } from "#payloads";

const path = "/etag/large";

export default performanceTest({
  id: { family: "etag", name: "large" },
  path,
  base: "json.large",
  varies: "validators",
  heft: 4,
  about:
    "The framework hashing the body it is about to send and writing the " +
    "validator it computed onto the response. Read against json.large, the " +
    "difference is the hash and the header. The tag is the framework's own, " +
    "so no two of them agree on it.",

  request: (c) => c.get(path).okWith(items.large).hasHeader("etag").fresh(),
});

etag.match_large

heft 4

base etag.large

The only row that cannot be sent until the framework has answered a different one: the validator is the framework's to produce. A 304 saves the write and nothing else, because the body is built and hashed before anything is compared.

Before this request, the test sends GET /etag/large once and reads its etag. That request is not measured.

Request

GET /etag/large
if-none-match"{etag}" the etag the priming request answered with

No body.

Expected response

HTTP 304

No body.

Test source, tests/etag/match-large.ts
tests/etag/match-large.tsopen on GitHub →
import { performanceTest } from "#kit";

const path = "/etag/large";

export default performanceTest({
  id: { family: "etag", name: "match_large" },
  path,
  base: "etag.large",
  varies: "conditional",
  heft: 4,
  about:
    "The only row that cannot be sent until the framework has answered a " +
    "different one: the validator is the framework's to produce. A 304 saves " +
    "the write and nothing else, because the body is built and hashed before " +
    "anything is compared.",

  request: async (c) => {
    const tag = await c.once(path, () => c.get(path).etag());

    return c.get(path).header("if-none-match", tag).notModified().emptyBody();
  },
});

etag.stale_large

heft 4

base etag.large

A conditional request whose validator does not match, answered in full. Read against etag.match_large, the difference is the write the 304 saved, and read against etag.large it is the comparison that failed.

Request

GET /etag/large
if-none-match"0000000000000000"

No body.

Expected response

HTTP 200
x-rb-serialis new, so the handler ran

payload items.large

{"size":"large","count":1425,"items":[{"id":1,"name":"slate-lamp-6647","category":"tools","priceCents":18928,"inStock":true},{"id":2,"name":"brass-hinge-5716","category":"garden","priceCents":17577,"inStock":true},{"id":3,"name":"linen-ring-6971","category":"kitchen","priceCents":5540,"inStock":true},{"id":4,"name":"copper-bolt-9217","category":"outdoor","priceCents":11562,"inStock":true},{"id":5,"name":"linen-lamp-8288","category":"office","priceCents":1413,"inStock":true},{"id":6,"name":"copper-pan-9308","category":"tools","priceCents":10795,"inStock":true},{"id":7,"name":"slate-seed-3051","category":"garden","priceCents":9667,"inStock":false},{"id":8,"name":"oak-lamp-8662","category":"kit
… 128,510 bytes total

Compared as parsed JSON, so key order and how a number is written do not matter.

Test source, tests/etag/stale-large.ts
tests/etag/stale-large.tsopen on GitHub →
import { performanceTest } from "#kit";
import { items } from "#payloads";

const path = "/etag/large";

/** A validator no framework computes. */
const stale = '"0000000000000000"';

export default performanceTest({
  id: { family: "etag", name: "stale_large" },
  path,
  base: "etag.large",
  varies: "stale_validator",
  heft: 4,
  about:
    "A conditional request whose validator does not match, answered in full. " +
    "Read against etag.match_large, the difference is the write the 304 " +
    "saved, and read against etag.large it is the comparison that failed.",

  request: (c) => c.get(path).header("if-none-match", stale).okWith(items.large).fresh(),
});

etag.small

heft 1

base json.small

The framework hashing the body it is about to send and writing the validator it computed onto the response. Read against json.small, the difference is the hash and the header. The tag is the framework's own, so no two of them agree on it.

Request

GET /etag/small

No body.

Expected response

HTTP 200
etagis present
x-rb-serialis new, so the handler ran

payload items.small

{"size":"small","count":1,"items":[{"id":1,"name":"slate-lamp-6647","category":"tools","priceCents":18928,"inStock":true}]}

Compared as parsed JSON, so key order and how a number is written do not matter.

Test source, tests/etag/small.ts
tests/etag/small.tsopen on GitHub →
import { performanceTest } from "#kit";
import { items } from "#payloads";

const path = "/etag/small";

export default performanceTest({
  id: { family: "etag", name: "small" },
  path,
  base: "json.small",
  varies: "validators",
  heft: 1,
  about:
    "The framework hashing the body it is about to send and writing the " +
    "validator it computed onto the response. Read against json.small, the " +
    "difference is the hash and the header. The tag is the framework's own, " +
    "so no two of them agree on it.",

  request: (c) => c.get(path).okWith(items.small).hasHeader("etag").fresh(),
});