skip to content

Query Parameters

depth, fields, content, filter and with-defaults let a client fetch exactly the slice of a large tree it needs. Pulling a whole config to read one counter is the mistake they prevent.

on this pageshow

questions

5

A RESTCONF dashboard pulls 40 MB of interface data to show one counter per interface; what do depth and fields each cut?

level: middleimportance: must knowfreq 16%

answer

  1. one prunes by level, one by name
  2. the target itself is level 1
  3. semicolons and parentheses select nodes
  4. paths below a list need every key
  5. both advertised as capability URIs

basics

~20 s

RESTCONF's depth prunes by level: counting the target as level 1, nodes deeper than level N are dropped, whatever their names. fields prunes by name: fields=interface(name;statistics/in-octets) returns just those nodes for every entry. Both are optional, advertised capabilities.

solid answer

~40 s

`depth` and `fields` prune a GET along different axes. `depth` counts levels from the target, which is level 1, and drops anything deeper; it cannot tell one leaf from another, so a `depth` large enough to reach `in-octets` also returns every other leaf at or above that level for every interface. `fields` prunes by name: on `ietf-interfaces:interfaces`, `fields=interface(name;statistics/in-octets)` returns only each entry's key and one counter — `;` separates selections, parentheses hold sub-selectors and `/` steps to a child. For one interface, a URI that addresses the leaf is simpler, but a RESTCONF path below a list must name every key, so only `fields` can take one leaf from every entry. Both are optional: look for `urn:ietf:params:restconf:capability:fields:1.0` and `depth:1.0` in the server's capability list, because an unexpected parameter draws `400 Bad Request`.

code

http · 8 lines
http
GET /restconf/data/ietf-interfaces:interfaces?depth=1 HTTP/1.1
Host: core1.example.net
Accept: application/yang-data+json

HTTP/1.1 200 OK
Content-Type: application/yang-data+json

{"ietf-interfaces:interfaces": {}}

go deeper

for a junior

Recall that RESTCONF can trim a GET, that depth limits how many levels come back, and that fields picks named nodes.

for a middle

Explain level counting from the target, the fields grammar with semicolons, parentheses and slashes, and why a path cannot take one leaf from every list entry.

for a senior

Size the cost of an untrimmed poll, pick fields over depth for per-entry counters, and build capability discovery with a fallback into the client.

for a principal

Treat retrieval shape as part of the telemetry design: decide when polling with fields is enough and when the device's management plane should not be polled at all.

## The failure being fixed A dashboard tile shows the inbound byte counter of every interface on a core router. It polls `GET /restconf/data/ietf-interfaces:interfaces` with no query parameters, and on a router with hundreds of interfaces and many augmenting modules the reply runs to tens of megabytes. Polled every 10 seconds, a 40 MB reply is 4 MB/s — 32 Mbit/s of management traffic — plus the device CPU spent serialising it, for a tile that needs one number per row. RFC 8040 gives a client two retrieval parameters to prevent exactly this, and they cut in different dimensions. ## depth — prune by level The **`depth`** parameter (RFC 8040 §4.8.2) limits how far below the target the reply descends: - the **target resource is level 1**; each child is one level deeper than its parent; - nodes with a level greater than `depth` are left out of the reply; - the value is an integer from 1 to 65535 or the string `unbounded`, which is the default; - it is allowed on `GET` for the API, datastore and data resources, and draws `400 Bad Request` anywhere else. For `ietf-interfaces:interfaces` the levels are: `interfaces` (1), each `interface` entry (2), the entry's own leaves and the `statistics` container (3), the counters inside `statistics` (4). `depth=3` returns every interface's name, description, enabled flag, status and speed with `statistics` present but empty; `depth=4` finally reaches `in-octets` — together with every other counter and every other level-3 node. Depth **cannot select by name**. Its real uses are different: `depth=1` answers "does this resource exist?" (the RFC's own example), and a small depth shows the shape of an unfamiliar tree without its bulk. ## fields — prune by name The **`fields`** parameter (§4.8.3) names the descendants to keep, and the server returns the target resource with everything else pruned — one message body, not a set of separate resources. Its grammar is short: | Syntax | Meaning | Example on `interfaces` | |---|---|---| | `a;b` | select several nodes | `fields=interface(name;enabled)` | | `a(b;c)` | sub-selectors under `a`, no `/` before `(` | `fields=interface(name;statistics/in-octets)` | | `a/b` | a child of a node | `fields=interface/statistics` | Identifiers follow the same `[module-name ":"] identifier` form as path segments, so a node from an augmenting module carries its module name. Nodes selected by `fields` — and their ancestors — count as level 1 for `depth`, so a small `depth` does not hide what `fields` asked for. ```http GET /restconf/data/ietf-interfaces:interfaces?fields=interface(name;statistics/in-octets) HTTP/1.1 Host: core1.example.net Accept: application/yang-data+json HTTP/1.1 200 OK Content-Type: application/yang-data+json {"ietf-interfaces:interfaces": {"interface": [ {"name": "eth0", "statistics": {"in-octets": "918273645512"}}, {"name": "eth1", "statistics": {"in-octets": "40211877"}} ]}} ``` Selecting `name` explicitly keeps every counter attached to its interface. ## Why not just address the leaf? For a single interface, a URI that names the leaf — `.../interface=eth0/statistics/in-octets` — is the simplest request of all. But a RESTCONF path that descends below a list entry must encode **all** of that entry's keys; partial instance identifiers are not supported (§3.5.3). There is no wildcard key, so "`in-octets` of every interface" cannot be written as one path. That is precisely the case `fields` exists for. ## Optional, so discover first RFC 8040 makes most query parameters optional. `depth` and `fields` each have a capability URI — `urn:ietf:params:restconf:capability:depth:1.0` and `urn:ietf:params:restconf:capability:fields:1.0` — that a supporting server MUST list in the `capability` leaf-list under `ietf-restconf-monitoring:restconf-state/capabilities`. A server MUST answer an unexpected query parameter with `400 Bad Request` and error-tag `invalid-value` (§4.8). So a robust client: 1. reads the capability list once per device; 2. uses `fields` when it is listed; 3. otherwise falls back to direct per-interface leaf URIs, or to `depth` plus `content=nonconfig` to shed configuration. ## Mistakes that survive code review - **Counting depth from the root.** Levels count from the target in the URI, so the same `depth` value means different things on `/data` and on one interface entry. - **Forgetting the key in `fields`.** Selecting only `statistics/in-octets` returns counters; selecting `name` as well is what lets the client say which interface each one belongs to. - **Dropping module prefixes.** A node that another module adds by augmentation carries that module's name in `fields`, just as it does in a path segment. - **Assuming silent tolerance.** An unsupported parameter is an error, not a no-op, so a client built against one server can fail outright on another. - **Mixing names into `depth`.** `depth` takes an integer or `unbounded`; it never takes a node name. ## Putting it together - `depth` = how far down; blind to names. - `fields` = which named nodes; the right tool for one leaf across many entries. - `content` = which half (configuration or state); coarse but mandatory to implement. For the dashboard, `fields=interface(name;statistics/in-octets)` turns a 40 MB poll into a reply of a few tens of kilobytes, and the tile shows the same numbers.

  • If a RESTCONF client sends depth=1 together with fields=interface(name), does the depth hide the names?
    No. RFC 8040 §4.8.2 gives nodes selected by `fields`, and their ancestors, a depth of 1, so they are included even though their real level is deeper. Children of the selected nodes still count normally from there, so `depth` keeps trimming anything beneath the selections.
  • How does a RESTCONF client learn whether fields is safe to send to a given device?
    It reads `ietf-restconf-monitoring:restconf-state/capabilities` and looks for `urn:ietf:params:restconf:capability:fields:1.0`; a supporting server MUST list it. If the URI is absent, sending `fields` risks `400 Bad Request` with `invalid-value`, since an unexpected parameter is an error, not something silently ignored.
  • Why does depth=3 on the interfaces container show statistics as an empty object?
    Levels count from the target: `interfaces` is 1, each `interface` entry 2, the entry's leaves and the `statistics` container 3. The counters inside `statistics` are level 4, deeper than the limit, so the container appears without its children — the same pattern as the empty containers in RFC 8040's own depth example.

depth is like printing a manual's table of contents to three heading levels: you get every heading down to that level, wanted or not. fields is like the index: you name the entries and get exactly those pages from every chapter.

saying these in an interview costs you the question

  • depth=2 returns the target and one named leaf beneath it.
  • depth counts from the datastore root, not from the target resource.
  • fields returns each selected node as a separate resource.
  • A list key can be wildcarded in the path to read every entry.
  • Every server must support depth and fields, so no discovery is needed.
  • A server silently ignores a query parameter it does not support.
open as a page

What does the RESTCONF content query parameter select, and what does a GET return when the parameter is left out?

level: juniorimportance: should knowfreq 12%

basics

~20 s

RESTCONF's content parameter chooses which descendants a GET returns: config (configuration only), nonconfig (state only) or all. Left out, it defaults to all, so the reply mixes settings and live state. Every server must support it.

open as a page

A RESTCONF POST adds a permit entry to an ordered-by-user ACL after its deny-all entry; how do insert and point fix the order?

level: middleimportance: should knowfreq 8%

basics

~20 s

RESTCONF's insert parameter defaults to last, so the new entry landed behind deny-all and never matches. insert=before with point set to the deny-all entry's path places it ahead; both work only on POST and PUT into ordered-by-user lists or leaf-lists.

open as a page

After a router upgrade, a RESTCONF backup job shows enabled=true vanishing from every interface; what changed, and how does with-defaults make the export deterministic?

level: seniorimportance: should knowfreq 9%

basics

~10 s

The server's advertised basic-mode changed, typically to trim, which omits leaves equal to their YANG default; enabled is still true. with-defaults=report-all returns every node regardless of basic-mode; report-all-tagged also marks the defaults.

open as a page

A RESTCONF event-stream collector reconnects after a ten-minute outage; how do filter, start-time and stop-time recover only the missed interface events?

level: seniorimportance: nice to knowfreq 5%

basics

~20 s

On reconnect, the RESTCONF collector sets start-time to its last received eventTime and omits stop-time, so missed notifications replay and live delivery follows. filter, an XPath 1.0 expression, keeps only interface events. Replay needs replay-support on that stream.

open as a page