skip to content

Which renderer does a web framework use when a request sends no Accept header or only a wildcard?

level: juniorimportance: should knowfreq 47%

answer

  1. no header means the same as wildcard
  2. no preference, so the server decides
  3. default type, route declaration, or priority
  4. 406 is impossible against a wildcard

basics

~20 s

Its default. A missing Accept header and a wildcard both mean no client preference, so the framework falls back to a configured default type, the route's first declared produced type, or the highest-priority renderer available.

solid answer

~40 s

Both cases collapse to the same thing: the client has expressed no constraint. A missing `Accept` is treated as `*/*`, and `*/*` matches every candidate, so ranking cannot separate them. The framework then applies its own preference, which is usually one of three: an explicitly configured default media type, the first media type the route declares it produces, or the highest-priority renderer in the registry that can write the returned value. This is why a service with several renderers still answers scripted clients consistently — and why adding a renderer can change what those clients receive if the default is implicit rather than configured. It is also why this path never produces `406`: something is always acceptable.

go deeper

for a junior

Recall that no Accept header and a wildcard both mean 'anything', and that the framework then falls back to its default format rather than failing the request.

for a middle

Explain the three places a default can come from — configured type, the route's declaration, the highest-priority renderer — and why an order-derived default is the fragile one.

for a senior

Point out that under-specified requests are the least tested path, since test clients usually pin Accept, while real monitors and scripts do not; make the response's concrete Content-Type non-negotiable.

for a principal

Decide whether the default is a platform-wide contract or a per-route choice. A single global default is simple and wrong for a minority of routes; per-route defaults are honest but only if declarations are enforced.

## Two inputs, one outcome A request can under-specify what it wants in two ways. It can omit `Accept` entirely — common for scripted clients, health checks, and hand-written tools — or it can send a wildcard such as `*/*`, which says every media type is acceptable. Servers treat the missing header as equivalent to the wildcard, so both arrive at the same place: **every candidate renderer is acceptable, and the client's preference cannot break the tie.** That matters because negotiation is a ranking mechanism. Given no ranking signal, it returns the whole candidate set unordered, and the choice moves entirely to the server. ## Where the default comes from Frameworks source the default from one of three places, and it is worth knowing which one your service uses: | Source | How it behaves | Failure mode | |---|---|---| | An explicitly configured default media type | Deterministic and global; every under-specified request lands on it | Wrong for the minority of routes that cannot produce it | | The route's first declared produced type | Deterministic per route and visible next to the handler | Silent when the route declares nothing | | The highest-priority renderer that can write the value | Needs no configuration at all | Depends on registry order, so a new dependency can change it | The third is the one that surprises teams. If the default is 'whatever sorts first in the registry', then registering a renderer — even one nobody intended for that route — can change the representation returned to every client that never sent `Accept`. ## Why this path cannot produce 406 `406 Not Acceptable` is the answer to *nothing I can produce is acceptable to you*. A wildcard accepts everything, so the condition cannot arise: if the route can produce anything at all, that something is acceptable. A candidate who says a missing `Accept` should be refused has inverted the rule. The only way an under-specified request fails is if the route has no renderer able to write the value at all, which is a server-side configuration fault, not a negotiation failure. ## What a wildcard does *not* mean - It does not mean 'send me every representation'. One response, one representation. - It does not mean 'pick at random'. The choice is the server's, and it should be stable across requests and deploys. - It does not mean the client is careless. Wildcards are the honest header for a proxy, a crawler, or a monitor that will not inspect the body. - It does not suppress an explicit format override in the URL, where the framework supports one; an override still pins the answer. ## The browser trap The mirror image of this question causes more incidents than the question itself. Browsers do not omit `Accept`; they send a rich, markup-first header with weights. A route that can produce both a markup representation and a structured one will therefore answer a browser and a scripted client differently — not because of a bug, but because one of them expressed a preference and the other did not. When a service is debugged by pasting a URL into a browser and then blamed for returning the 'wrong' format, this is nearly always the cause. ## Making the default explicit The practical advice a candidate should be able to give: 1. **Declare produced types on routes** that are meant to speak one format, so the default is local and visible rather than global and inherited. 2. **Configure the default explicitly** rather than relying on registry ordering, so it survives dependency changes. 3. **Always send the concrete `Content-Type`** on the response, so a client that expressed no preference is still told what it got. 4. **Cover the no-`Accept` case in tests.** Most test clients send a specific `Accept` by convention, so the path that real monitors and scripts actually take is the one least exercised. ## What interviewers listen for The short, correct answer is 'the framework's default, because a missing header means the same as a wildcard'. The follow-up that separates candidates is *where that default comes from* — and whether they notice that an implicit, order-derived default is a latent behaviour change waiting on the next dependency bump.

  • Why does the same route answer a browser and a scripted client with different representations?
    Because only one of them stated a preference. Browsers send a rich markup-first `Accept` with weights, so ranking picks the markup representation where one exists; a script that sends no header gets the server's default instead. Nothing is broken — the two requests supplied different negotiation input for the same route.
  • If the default comes from registry order rather than configuration, what can change it?
    Anything that changes the registry: adding a dependency that self-registers a renderer, reordering registration code, or a conditional configuration that only activates in one environment. The route is untouched, yet clients that send no `Accept` start receiving a different representation — which is why an explicit default is worth the configuration line.

saying these in an interview costs you the question

  • Claims a missing Accept header should be answered with 406.
  • Thinks a wildcard Accept makes the framework choose at random.
  • Believes the default format cannot be configured per route.
  • Confuses the default response format with the request's Content-Type.
  • Assumes browsers omit Accept, so the default covers them.