In Postman's SDK, why can a request whose URL matches a proxy entry's match pattern still be sent directly?
answer
- Two pattern properties, one fixed order
- One of them is a veto
- Which list is read first?
- A bypass hit ends the evaluation
- match is never reached after bypass
basics
~10 sProxyConfig.test checks the bypass list before the match pattern, so any bypass hit ends the evaluation and the request goes direct no matter what match says. Bypass is a veto, not a tie-breaker.
solid answer
~40 sIn the Postman SDK, one proxy entry is a `ProxyConfig`, and `ProxyConfig.test(url)` decides whether that entry applies. It tests the URL against `bypass` **first**: if any bypass pattern covers the URL it returns false immediately, and `match` is never consulted. Only when nothing in `bypass` hits does it test `match`. Both are Chrome-grammar `UrlMatchPattern`s over scheme, host and path, so a broad bypass such as `http://*/*` silently outranks a carefully written `match`. The practical rule that follows: when a call you expected to be proxied goes direct, narrow the `bypass`, never widen the `match` — widening `match` cannot reach the code path that a bypass hit already ended.
code
json · 8 lines{
"host": "proxy.internal",
"port": 8080,
"match": "http+https://*/*",
"bypass": ["https://*.internal/*"],
"tunnel": false,
"disabled": false
}go deeper
Be ready to say that a proxy entry carries both an apply-to pattern and a bypass list, and that the bypass list is what keeps certain URLs off the proxy.
Explain the mechanics: ProxyConfig.test checks bypass first and returns false on any hit, so match is never consulted afterwards. Both properties use the same scheme-host-path pattern grammar.
Show the diagnostic instinct. When a call goes direct unexpectedly, read the bypass list before touching match, and reason with full URLs rather than hostnames.
Own the policy angle: a shared bypass list is a blunt instrument whose breadth outranks every match anyone writes, so treat widening one as a change with team-wide blast radius.
## What a proxy entry is in Postman The Postman SDK (`postman-collection`) models one proxy entry as a **`ProxyConfig`**. An entry names the proxy itself with `host` and `port`, carries the two pattern properties that decide which URLs it applies to — `match` and `bypass` — plus a `tunnel` switch, a `disabled` switch, and the credential fields `authenticate`, `username` and `password`. Nothing about a proxy is part of the saved collection document. Proxy entries are client and runtime configuration handed to a run, not fields of the portable artefact, which is why two people running the same collection can take different network paths without either file differing. The method that answers *"does this entry apply to this URL?"* is **`ProxyConfig.test(url)`**, and this question is entirely about the order in which `test` consults the two properties. ## The order: bypass first, match second `test` evaluates `bypass` **before** `match`: 1. Take the URL under test. 2. Test it against the patterns in `bypass`. **If any of them matches, the answer is `false` immediately** — this entry does not apply and the request is not proxied through it. 3. Only if nothing in `bypass` matched, test the URL against `match`. 4. Return whether `match` matched. So `bypass` is a **veto evaluated first**, not a refinement applied to the set `match` already selected. There is no scoring, no specificity comparison, no "the more precise pattern wins". One bypass hit ends the evaluation before `match` is ever read. | URL hits `bypass` | URL hits `match` | `test` returns | Effect | |---|---|---|---| | yes | yes | `false` | direct — the bypass decided it | | yes | no | `false` | direct | | no | yes | `true` | this entry's proxy is used | | no | no | `false` | this entry does not apply | The first row is the entire point: **the combination people expect to be "proxied, because it matched" is the combination that goes direct.** ## Both properties speak the same grammar `match` is a single **Chrome-grammar `UrlMatchPattern`** — the `<scheme>://<host><path>` form browser extensions use, such as `https://*.example.com/*`, plus Postman's `http+https` scheme spelling that covers both schemes at once. `bypass` is a list of patterns in that same grammar. They are **not** regular expressions and **not** bare hostnames. Because the grammar carries the scheme and the path as well as the host, two URLs on the same host can land on opposite sides of the same test — different scheme, different path, different verdict. That shared grammar is what makes the ordering dangerous rather than merely surprising: a bypass pattern is exactly as broad as whoever wrote it made it, and a broad one silently outranks a carefully written `match`. ## How it bites in practice - Someone adds `http://*/*` to `bypass` to "keep local development direct", and every plain-HTTP call in the workspace stops being proxied, including the calls the entry was written for. - A bypass pattern left over from an old network still covers a host that has since moved behind the proxy. The entry looks correct on inspection, because its `match` is correct. - A wildcard host bypass such as `https://*.internal/*` also covers the API host under that suffix, so a "we only bypass the intranet" intent quietly covers traffic nobody meant to exempt. - Someone widens `match` to fix a call that is going direct, and nothing changes — because a bypass pattern is what returned `false`, and `match` was never consulted. ## Debugging it 1. Work with the **full URL**, not the hostname. Scheme and path participate in both tests. 2. Read `bypass` first, exactly as the code does, and satisfy yourself that no pattern in it covers that URL. 3. Only then read `match`. 4. Remember the scope of the answer: `ProxyConfig.test` speaks for **one entry**. Choosing among several entries is a separate step performed by the list that holds them. The fix for an over-broad bypass is always to **narrow the bypass**, never to widen the match. Widening `match` cannot beat a bypass hit, because `match` is not reached after one. ## What this is not about Whether the resulting connection is tunnelled, and what tunnelling means on the wire, are HTTP-protocol subjects rather than Postman-configuration ones. The mechanism here is narrow and complete on its own: a two-property test with a fixed order, applied to one entry at a time, whose first property is allowed to end the question.
- Someone widens the match pattern to fix a call that is going direct. Why does nothing change?Because `match` is only consulted when no `bypass` pattern covered the URL. If a bypass hit is what returned false, `test` never reaches `match`, so any widening of it is unobservable. The fix is to narrow the bypass pattern that covers the URL, which is the property that actually decided the outcome.
- Does ProxyConfig.test alone decide whether a request is proxied?No. `test` speaks for one entry only. Choosing among several entries is done by the list that holds them, which skips disabled entries and returns the first that applies. An entry can pass its own `test` and still lose to an earlier entry, so a true result is necessary but not sufficient.
- Why can two URLs on the same host get opposite answers from the same entry?Because both `bypass` and `match` are Chrome-grammar patterns of the form scheme, host and path — the host is only one part. A pattern written for `https` misses the `http` call to that host, and a pattern with a path prefix misses URLs outside it, so identical hosts routinely land on opposite sides.
A guest list and a banned list at a door: the bouncer reads the banned list first, so being on the guest list changes nothing.
saying these in an interview costs you the question
- Says match is evaluated first and bypass refines the result
- Claims the more specific of the two patterns wins
- Treats bypass as a list of bare hostnames
- Suggests widening match to overcome a bypass hit
- Assumes same host always means same proxy verdict
- Thinks a passing test guarantees that entry is used