# yaml-language-server: $schema=https://json.schemastore.org/traefik-v3-file-provider.json http: routers: whoami-cache: rule: PathPrefix(`/whoami-cache`) middlewares: - whoami-cache service: whoami # Stale responses: here the backend sends `stale-while-revalidate` and `stale-if-error`, and its status can be # changed: `curl -d 503 http://localhost:8080/whoami-stale/health`, then GET the same URL whoami-stale: rule: PathPrefix(`/whoami-stale`) middlewares: - whoami-client # acts on the Cache-Control of clients: e2e/tests/stale.hurl reloads like a browser - whoami-stale-headers # after the cache: for the cache, these headers come from the backend - whoami-stale-prefix service: whoami # Same thing for a backend that sends neither: the cache is configured to serve its responses stale whoami-stale-default: rule: PathPrefix(`/whoami-stale-default`) middlewares: - whoami-stale-default - whoami-stale-prefix service: whoami # Variants: here the backend answers by `Accept-Language` (whoami echoes the request headers) and compresses # by `Accept-Encoding`: `curl -H 'Accept-Language: fr' --compressed http://localhost:8080/whoami-vary` whoami-vary: rule: PathPrefix(`/whoami-vary`) middlewares: - whoami-vary - whoami-vary-headers # after the cache: for the cache, `Vary` and the compression come from the backend - whoami-vary-compress service: whoami # Cookies: here the backend sets a cookie and tells caches not to store it (`private="Set-Cookie"`): the # response is cached without it. /whoami-cookie-public only says `public`: it is not cached at all whoami-cookie: rule: PathPrefix(`/whoami-cookie`) middlewares: - whoami-cache - whoami-cookie-headers # after the cache: for the cache, these headers come from the backend service: whoami whoami-cookie-public: rule: PathPrefix(`/whoami-cookie-public`) middlewares: - whoami-cache - whoami-cookie-public-headers service: whoami # Query sorting: here `?a=1&b=2` and `?b=2&a=1` share the same cached response whoami-sort-query: rule: PathPrefix(`/whoami-sort-query`) middlewares: - whoami-sort-query service: whoami # Middleware names: here two routers match the same URL, each with a middleware of its own. Their responses # are stored apart: `curl -H 'X-Tenant: b' http://localhost:8080/whoami-key` never gets those of the other one whoami-key: rule: PathPrefix(`/whoami-key`) middlewares: - whoami-key service: whoami whoami-key-tenant: rule: PathPrefix(`/whoami-key`) && Header(`X-Tenant`, `b`) middlewares: - whoami-key-tenant service: whoami # TLS to Redis: here the cache is in `cache-tls`, whose certificate is verified with `redis.tls.ca`. # /whoami-tls-untrusted has no `redis.tls.ca`: the certificate is refused and the cache bypassed whoami-tls: rule: PathPrefix(`/whoami-tls`) middlewares: - whoami-tls service: whoami whoami-tls-untrusted: rule: PathPrefix(`/whoami-tls-untrusted`) middlewares: - whoami-tls-untrusted service: whoami # Request directives: by default the cache ignores the Cache-Control of clients, which this middleware acts on: # `curl -H 'Cache-Control: no-cache' http://localhost:8080/whoami-client` reaches the backend whoami-client: rule: PathPrefix(`/whoami-client`) middlewares: - whoami-client service: whoami # Authorization header fields: here basicAuth (alice:alice-secret, bob:bob-secret) replaces Authorization with X-WebAuth-User, which # the cache is told about: the page of alice is not served to bob. `curl -u alice:alice-secret …/whoami-authorization` whoami-authorization: rule: PathPrefix(`/whoami-authorization`) middlewares: - whoami-auth # before the cache: a hit is served without running what comes after it - whoami-authorization service: whoami # Cache-Status hidden from clients: `Age` still tells a response that comes from the cache whoami-hidden: rule: PathPrefix(`/whoami-hidden`) middlewares: - whoami-hidden service: whoami whoami: rule: PathPrefix(`/whoami`) service: whoami middlewares: whoami-cookie-headers: headers: customResponseHeaders: Cache-Control: 'max-age=60, private="Set-Cookie"' Set-Cookie: "sid=e2e-secret" whoami-cookie-public-headers: headers: customResponseHeaders: Cache-Control: "public, max-age=60" Set-Cookie: "sid=e2e-secret" whoami-vary-headers: headers: customResponseHeaders: Cache-Control: "max-age=60" # On every response: `compress` only adds `Vary: Accept-Encoding` to those it compresses, and a response # without `Vary` would be served to all Vary: "Accept-Language, Accept-Encoding" whoami-vary-compress: compress: encodings: [ br, gzip ] minResponseBodyBytes: 1 # whoami's responses are tiny whoami-stale-headers: headers: customResponseHeaders: Cache-Control: "max-age=2, stale-while-revalidate=10, stale-if-error=60" whoami-stale-prefix: stripPrefix: prefixes: - /whoami-stale-default # first: the other one is its prefix - /whoami-stale whoami-cache: plugin: traedis: redis: dsn: "redis://cache:6379/2" defaultTtl: 5m # 0 by default: whoami sends no Cache-Control, nothing would be stored maxBodyBytes: 5120 # 5 KiB collapseTimeout: 5s # 0 by default: concurrent requests for a URL being fetched wait for its response whoami-client: plugin: traedis: redis: dsn: "redis://cache:6379/2" defaultTtl: 5m followClientCacheControl: true # off by default: request directives are advisory (RFC 9111 §5.2.1) maxBodyBytes: 2048 # 2 KiB: whoami echoes the request headers, large ones make a response too large to be stored whoami-auth: basicAuth: users: - "alice:$apr1$gJWplQWT$0ny9VbN3AkZhHHs5oHQBS1" - "bob:$apr1$8gJoVHET$x6klEdUMV.bq8/w9aBTtI/" headerField: X-WebAuth-User removeHeader: true # the cache no longer sees Authorization: only authorizationHeaders tell it who the client is whoami-authorization: plugin: traedis: redis: dsn: "redis://cache:6379/2" defaultTtl: 5m authorizationHeaders: [ X-WebAuth-User ] whoami-hidden: plugin: traedis: redis: dsn: "redis://cache:6379/2" defaultTtl: 5m exposeCacheStatus: false whoami-vary: plugin: traedis: redis: dsn: "redis://cache:6379/2" maxVariants: 3 # per URL; 16 by default whoami-sort-query: plugin: traedis: redis: dsn: "redis://cache:6379/2" defaultTtl: 5m sortQuery: true # off by default: for RFC 9111, these are two URLs whoami-key: plugin: traedis: redis: dsn: "redis://cache:6379/2" defaultTtl: 5m exposeKey: true # the Redis key in `Cache-Status`: it starts with the name of the middleware whoami-key-tenant: plugin: traedis: redis: dsn: "redis://cache:6379/2" defaultTtl: 5m exposeKey: true whoami-tls: plugin: traedis: redis: dsn: "rediss://cache-tls:6379/0" tls: ca: /certs/redis.crt # self-signed: not one of the authorities of the system defaultTtl: 5m whoami-tls-untrusted: plugin: traedis: redis: dsn: "rediss://cache-tls:6379/0" whoami-stale-default: plugin: traedis: redis: dsn: "redis://cache:6379/2" defaultTtl: 2s defaultStaleWhileRevalidate: 10s defaultStaleIfError: 1m followClientCacheControl: true # e2e/tests/stale.hurl reloads like a browser services: whoami: loadBalancer: servers: - url: "http://whoami:80"