skip to content

Per-Request Behaviour

Per-entry switches the sending program reads before a call: follow a redirect or not, touch the shared cookie jar or not, check a certificate strictly or not. Interviewers ask which level wins.

part ofAPI & DB clientsoverview, primer and where to startread it →
on this pageshow

explore

questions

4

A Postman collection sets followRedirects false and a request inside sets it true; which value does the run use?

level: middleimportance: must knowfreq 42%

answer

  1. The tree is walked, not just the item
  2. Ancestors merged, including the collection root
  3. Nearest declaration wins each member
  4. Merge is per member, not wholesale
  5. Undeclared members fall to runtime defaults

basics

~10 s

The request's value wins. Postman's SDK resolves an item's protocolProfileBehavior by walking every ancestor including the collection root and merging their blocks member by member, so the declaration nearest the request decides each member.

solid answer

~40 s

The **request's** value is used: `true`. The SDK's `Item#getProtocolProfileBehaviorResolved` builds the effective block by walking the item's ancestors with `forEachParent({withRoot: true})` — folders and the collection root included — and merging what it finds, so the **nearest declaration wins**. Two details decide most follow-ups. First, the merge is **per member**: a request that declares `followRedirects` overrides only that member and keeps everything else it inherited. Second, a member declared nowhere is not undefined — the runtime resolves the merged block through `resolveWithProtocolProfileBehavior()` against `defaultOpts`. What following a redirect then does on the wire is HTTP's business; this field settles only **which declaration of the switch is in force**.

code

json · 10 lines
json
{
  "protocolProfileBehavior": { "followRedirects": false, "strictSSL": true },
  "item": [
    {
      "name": "alias",
      "protocolProfileBehavior": { "followRedirects": true },
      "request": { "method": "GET", "url": "https://example.test/alias" }
    }
  ]
}

go deeper

for a junior

Be ready to state the rule plainly: the declaration closest to the request wins, and the collection root is the furthest away. Knowing that much already answers the usual screening version of this question.

for a middle

Be ready to name the resolver and the walk, explain that ancestors including the root are merged member by member, and add that a member declared nowhere still resolves against the runtime's defaults.

for a senior

Be ready to use it under pressure: given one entry misbehaving in a large collection, describe how you would determine which level supplied each member and how you would keep the override visible afterwards.

for a principal

Be ready to argue a convention. Decide whether switches belong as a root house rule with rare exceptions or per entry, and justify it in terms of reviewability and predictable behaviour as a shared collection grows.

## The answer, then the mechanism The run uses the **request's** value. A `protocolProfileBehavior` member declared closer to the request beats the same member declared further away, and the collection root is the furthest away of all. This is the question interviewers actually ask about this field, because a collection is a tree and every level of it may declare the same switch. The useful answer names the rule (**nearest wins**), the resolver that implements it, and the two edges: merging is per member, and an undeclared member still has a value. ## The resolver The SDK exposes the effective value through `Item#getProtocolProfileBehaviorResolved`. What it does: 1. Starts from the item being sent. 2. Walks its ancestors with `forEachParent({withRoot: true})` — every enclosing folder, and the collection root itself, which is what `withRoot` includes. 3. Merges the blocks it finds so that a value declared nearer the item overrides the same member declared further up. 4. Returns one merged object, which is the entry's effective behaviour block. Notice that the request's own stored block is not the answer on its own, and neither is the root's. Only the resolver's output describes what will actually happen. ## Merge, not replace The single most common misconception is that a request-level block **replaces** the inherited one. It does not; the merge is member by member. Take a root that declares two members and a request that declares one: ```json { "protocolProfileBehavior": { "followRedirects": false, "strictSSL": true }, "item": [ { "name": "alias", "protocolProfileBehavior": { "followRedirects": true }, "request": { "method": "GET", "url": "https://example.test/alias" } } ] } ``` The effective block for `alias` is `followRedirects: true` **and** `strictSSL: true`. The request overrode exactly the member it named and inherited the other. - A member declared only at the root applies everywhere below it. - A member declared on a folder applies to that subtree, at any depth. - A member declared on the request applies to that one entry. - A member declared at two levels resolves to the nearer one. ## Then the runtime's defaults Inheritance is only the first half. The merged block is handed to the runtime, which resolves it through `resolveWithProtocolProfileBehavior()` against `defaultOpts`. So a member that nobody declared anywhere in the tree is not missing at send time — it takes the runtime's own value. That is why *nothing declared it* and *it is off* are different statements, and why a candidate who says a member is simply absent has answered half the question. | Where a member is declared | Effective value | |---|---| | Request only | the request's | | Folder only | the folder's, for the whole subtree | | Root only | the root's, everywhere below | | Root and request | the request's — nearest wins | | Folder and a nested folder | the nested folder's | | Nowhere | the runtime's default from `defaultOpts` | ## Why this matters in practice - **Diagnosis.** When one entry in a shared collection behaves unlike its neighbours, the difference is often a block on that entry or on a folder above it, and you find it by asking which level supplied each member. - **Review.** A root-level house rule with a small number of deliberate, visible exceptions is far easier to reason about than the same switches scattered across dozens of entries. - **Prediction.** Because the merge is per member, adding one member to a request is a narrow change; it does not silently discard the rest of what that request inherited. ## Where the answer stops The rule settles **which declaration of a switch is in force** and nothing beyond it. What a client re-sends when it does follow a redirect, whether a credential survives a cross-origin hop, how a redirect loop is stopped and which status code rewrites the method belong to the HTTP redirect and status-code topics. Certificate verification as a discipline belongs to application security, cookie attribute meanings to HTTP cookies, and the shared cookie store, the proxy list and certificate selection to the neighbouring transport topics. Answer the inheritance question; cede the protocol question explicitly, because doing so is itself a sign of a candidate who knows where the boundary is. ## Mistakes to avoid - Saying the collection root wins because it is the broader scope. - Saying a request-level block replaces everything inherited. - Forgetting that the root participates at all, and stopping at the nearest folder. - Treating an undeclared member as unset rather than as the runtime's default.

  • Does the request's block replace the inherited block or merge into it?
    It merges. The resolver combines the blocks member by member, so a request that declares one member overrides that member alone and keeps every other member it inherited from a folder or the root. Replacement would make narrow overrides impossible to write safely.
  • Two folders between the request and the root both declare the same member. Which applies?
    The inner folder's. The rule is distance from the item, not depth from the root, so every ancestor is merged in and the nearest declaration of a given member wins. The outer folder still supplies any member the inner one does not name.
  • What is in force if no level in the collection declares a given member?
    The runtime's value. After inheritance, the merged block is resolved through `resolveWithProtocolProfileBehavior()` against `defaultOpts`, so every member the runtime knows has a value at send time even when the file is silent about it.

saying these in an interview costs you the question

  • Saying the collection root wins as the broader scope
  • Claiming a request block replaces the whole inherited block
  • Forgetting that the root is included in the walk
  • Treating an undeclared member as unset rather than defaulted
  • Explaining redirect behaviour instead of which declaration wins
open as a page

In a saved Postman collection file, what is the protocolProfileBehavior block and which entries may carry one?

level: juniorimportance: should knowfreq 34%

basics

~10 s

protocolProfileBehavior is a collection-format field holding per-entry sending switches such as strictSSL, disableCookies and followRedirects. The collection root, a folder and an individual request may each declare one, and the nearest declaration wins.

open as a page

The Postman collection format declares protocolProfileBehavior with no properties, so which component defines its legal keys?

level: middleimportance: should knowfreq 26%

basics

~10 s

The runtime does. The collection format's schema declares protocolProfileBehavior as an object with no properties, so any key validates; the runtime's PPB_OPTS list is the only real enumeration, resolved against the runtime's own defaults.

open as a page

In a large shared Postman collection, how does protocolProfileBehavior inheritance differ from auth and event inheritance?

level: seniorimportance: should knowfreq 20%

basics

~20 s

Postman has three unrelated inheritance rules. Declared credentials resolve to a single nearest declaration, inherited scripts stack so every one of them runs, and protocolProfileBehavior merges member by member with the nearest declaration winning each member.

open as a page