Skip to main content

3. Expansion

The process of URI Template expansion is to scan the template string from beginning to end, copying literal characters and replacing each expression with the result of applying the expression's operator to the value of each variable named in the expression. Each variable's value MUST be formed prior to template expansion.

The requirements on expansion for each aspect of the URI Template grammar are defined in this section. A non-normative algorithm for the expansion process as a whole is provided in Appendix A.

If a template processor encounters a character sequence outside an expression that does not match the grammar, then processing of the template SHOULD cease, the URI reference result SHOULD contain the expanded part of the template followed by the remainder unexpanded, and the location and type of error SHOULD be indicated to the invoking application.

If an error is encountered in an expression, such as an operator or value modifier that the template processor does not recognize or does not yet support, or a character is found that is not allowed by the grammar, then the unprocessed parts of the expression SHOULD be copied to the result unexpanded, processing of the remainder of the template SHOULD continue, and the location and type of error SHOULD be indicated to the invoking application.

If an error occurs, the result returned might not be a valid URI reference; it will be an incompletely expanded template string that is only intended for diagnostic use.

3.1. Literal Expansion​

If the literal character is allowed anywhere in the URI syntax (unreserved / reserved / pct-encoded ), then it is copied directly to the result string. Otherwise, the pct-encoded equivalent of the literal character is copied to the result string by first encoding the character as its sequence of octets in UTF-8 and then encoding each such octet as a pct-encoded triplet.

3.2. Expression Expansion​

Each expression is indicated by an opening brace ("{") character and continues until the next closing brace ("}"). Expressions cannot be nested.

An expression is expanded by determining its expression type and then following that type's expansion process for each comma-separated varspec in the expression. Level 1 templates are limited to the default operator (simple string value expansion) and a single variable per expression. Level 2 templates are limited to a single varspec per expression.

The expression type is determined by looking at the first character after the opening brace. If the character is an operator, then remember the expression type associated with that operator for later expansion decisions and skip to the next character for the variable-list. If the first character is not an operator, then the expression type is simple string expansion and the first character is the beginning of the variable-list.

The examples in the subsections below use the following definitions for variable values:

count := ("one", "two", "three")
dom := ("example", "com")
dub := "me/too"
hello := "Hello World!"
half := "50%"
var := "value"
who := "fred"
base := "http://example.com/home/"
path := "/foo/bar"
list := ("red", "green", "blue")
keys := [("semi",";"),("dot","."),("comma",",")]
v := "6"
x := "1024"
y := "768"
empty := ""
empty_keys := []
undef := null

3.2.1. Variable Expansion​

A variable that is undefined (Section 2.3) has no value and is ignored by the expansion process. If all of the variables in an expression are undefined, then the expression's expansion is the empty string.

Variable expansion of a defined, non-empty value results in a substring of allowed URI characters. As described in Section 1.6, the expansion process is defined in terms of Unicode code points in order to ensure that non-ASCII characters are consistently pct-encoded in the resulting URI reference. One way for a template processor to obtain a consistent expansion is to transcode the value string to UTF-8 (if it is not already in UTF-8) and then transform each octet that is not in the allowed set into the corresponding pct-encoded triplet. Another is to map directly from the value's native character encoding to the set of allowed URI characters, with any remaining disallowed characters mapping to the sequence of pct-encoded triplets that correspond to the octet(s) of that character when encoded as UTF-8 [RFC3629].

The allowed set for a given expansion depends on the expression type: reserved ("+") and fragment ("#") expansions allow the set of characters in the union of ( unreserved / reserved / pct-encoded ) to be passed through without pct-encoding, whereas all other expression types allow only unreserved characters to be passed through without pct-encoding. Note that the percent character ("%") is only allowed as part of a pct-encoded triplet and only for reserved/fragment expansion: in all other cases, a value character of "%" MUST be pct-encoded as "%25" by variable expansion.

If a variable appears more than once in an expression or within multiple expressions of a URI Template, the value of that variable MUST remain static throughout the expansion process (i.e., the variable must have the same value for the purpose of calculating each expansion). However, if reserved characters or pct-encoded triplets occur in the value, they will be pct-encoded by some expression types and not by others.

For a variable that is a simple string value, expansion consists of appending the encoded value to the result string. An explode modifier has no effect. A prefix modifier limits the expansion to the first max-length characters of the decoded value. If the value contains multi-octet or pct-encoded characters, care must be taken to avoid splitting the value in mid-character: count each Unicode code point as one character.

For a variable that is an associative array, expansion depends on both the expression type and the presence of an explode modifier. If there is no explode modifier, expansion consists of appending a comma-separated concatenation of each (name, value) pair that has a defined value. If there is an explode modifier, expansion consists of appending each pair that has a defined value as either "name=value" or, if the value is the empty string and the expression type does not indicate form-style parameters (i.e., not a "?" or "&" type), simply "name". Both name and value strings are encoded in the same way as simple string values. A separator string is appended between defined pairs according to the expression type, as defined by the following table:

Type    Separator
"," (default)
+ ","
# ","
. "."
/ "/"
; ";"
? "&"
& "&"

For a variable that is a list of values, expansion depends on both the expression type and the presence of an explode modifier. If there is no explode modifier, the expansion consists of a comma-separated concatenation of the defined member string values. If there is an explode modifier and the expression type expands named parameters (";", "?", or "&"), then the list is expanded as if it were an associative array in which each member value is paired with the list's varname. Otherwise, the value will be expanded as if it were a list of separate variable values, each value separated by the expression type's associated separator as defined by the table above.

Example Template     Expansion
{count}            one,two,three
{count*} one,two,three
{/count} /one,two,three
{/count*} /one/two/three
{;count} ;count=one,two,three
{;count*} ;count=one;count=two;count=three
{?count} ?count=one,two,three
{?count*} ?count=one&count=two&count=three
{&count*} &count=one&count=two&count=three

3.2.2. Simple String Expansion: {var}​

Simple string expansion is the default expression type when no operator is given.

For each defined variable in the variable-list, perform variable expansion, as defined in Section 3.2.1, with the allowed characters being those in the unreserved set. If more than one variable has a defined value, append a comma (",") to the result string as a separator between variable expansions.

Example Template     Expansion
{var}              value
{hello} Hello%20World%21
{half} 50%25
O{empty}X OX
O{undef}X OX
{x,y} 1024,768
{x,hello,y} 1024,Hello%20World%21,768
?{x,empty} ?1024,
?{x,undef} ?1024
?{undef,y} ?768
{var:3} val
{var:30} value
{list} red,green,blue
{list*} red,green,blue
{keys} semi,%3B,dot,.,comma,%2C
{keys*} semi=%3B,dot=.,comma=%2C

3.2.3. Reserved Expansion: {+var}​

Reserved expansion, as indicated by the plus ("+") operator for Level 2 and above templates, is identical to simple string expansion except that the substituted values may also contain pct-encoded triplets and characters in the reserved set.

For each defined variable in the variable-list, perform variable expansion, as defined in Section 3.2.1, with the allowed characters being those in the set (unreserved / reserved / pct-encoded). If more than one variable has a defined value, append a comma (",") to the result string as a separator between variable expansions.

Example Template        Expansion
{+var}                value
{+hello} Hello%20World!
{+half} 50%25
{base}index           http%3A%2F%2Fexample.com%2Fhome%2Findex
{+base}index http://example.com/home/index
O{+empty}X OX
O{+undef}X OX
{+path}/here          /foo/bar/here
here?ref={+path} here?ref=/foo/bar
up{+path}{var}/here up/foo/barvalue/here
{+x,hello,y} 1024,Hello%20World!,768
{+path,x}/here /foo/bar,1024/here
{+path:6}/here        /foo/b/here
{+list} red,green,blue
{+list*} red,green,blue
{+keys} semi,;,dot,.,comma,,
{+keys*} semi=;,dot=.,comma=,

3.2.4. Fragment Expansion:​

Fragment expansion, as indicated by the crosshatch ("#") operator for Level 2 and above templates, is identical to reserved expansion except that a crosshatch character (fragment delimiter) is appended first to the result string if any of the variables are defined.

Example Template     Expansion
{#var}             #value
{#hello} #Hello%20World!
{#half} #50%25
foo{#empty} foo#
foo{#undef} foo
{#x,hello,y} #1024,Hello%20World!,768
{#path,x}/here #/foo/bar,1024/here
{#path:6}/here #/foo/b/here
{#list} #red,green,blue
{#list*} #red,green,blue
{#keys} #semi,;,dot,.,comma,,
{#keys*} #semi=;,dot=.,comma=,

3.2.5. Label Expansion with Dot-Prefix: {.var}​

Label expansion, as indicated by the dot (".") operator for Level 3 and above templates, is useful for describing URI spaces with varying domain names or path selectors (e.g., filename extensions).

For each defined variable in the variable-list, append "." to the result string and then perform variable expansion, as defined in Section 3.2.1, with the allowed characters being those in the unreserved set.

Since "." is in the unreserved set, a value that contains a "." has the effect of adding multiple labels.

Example Template     Expansion
{.who}             .fred
{.who,who} .fred.fred
{.half,who} .50%25.fred
www{.dom*} www.example.com
X{.var} X.value
X{.empty} X.
X{.undef} X
X{.var:3} X.val
X{.list} X.red,green,blue
X{.list*} X.red.green.blue
X{.keys} X.semi,%3B,dot,.,comma,%2C
X{.keys*} X.semi=%3B.dot=..comma=%2C
X{.empty_keys} X
X{.empty_keys*} X

3.2.6. Path Segment Expansion: {/var}​

Path segment expansion, as indicated by the slash ("/") operator in Level 3 and above templates, is useful for describing URI path hierarchies.

For each defined variable in the variable-list, append "/" to the result string and then perform variable expansion, as defined in Section 3.2.1, with the allowed characters being those in the unreserved set.

Note that the expansion process for path segment expansion is identical to that of label expansion aside from the substitution of "/" instead of ".". However, unlike ".", a "/" is a reserved character and will be pct-encoded if found in a value.

Example Template     Expansion
{/who}             /fred
{/who,who} /fred/fred
{/half,who} /50%25/fred
{/who,dub} /fred/me%2Ftoo
{/var} /value
{/var,empty} /value/
{/var,undef} /value
{/var,x}/here /value/1024/here
{/var:1,var} /v/value
{/list} /red,green,blue
{/list*} /red/green/blue
{/list*,path:4} /red/green/blue/%2Ffoo
{/keys} /semi,%3B,dot,.,comma,%2C
{/keys*} /semi=%3B/dot=./comma=%2C

3.2.7. Path-Style Parameter Expansion: {;var}​

Path-style parameter expansion, as indicated by the semicolon (";") operator in Level 3 and above templates, is useful for describing URI path parameters, such as "path;property" or "path;name=value".

For each defined variable in the variable-list:

  • append ";" to the result string;

  • if the variable has a simple string value or no explode modifier is given, then:

    • append the variable name (encoded as if it were a literal string) to the result string;

    • if the variable's value is not empty, append "=" to the result string;

  • perform variable expansion, as defined in Section 3.2.1, with the allowed characters being those in the unreserved set.

Example Template     Expansion
{;who}             ;who=fred
{;half} ;half=50%25
{;empty} ;empty
{;v,empty,who} ;v=6;empty;who=fred
{;v,bar,who} ;v=6;who=fred
{;x,y} ;x=1024;y=768
{;x,y,empty} ;x=1024;y=768;empty
{;x,y,undef} ;x=1024;y=768
{;hello:5} ;hello=Hello
{;list} ;list=red,green,blue
{;list*} ;list=red;list=green;list=blue
{;keys} ;keys=semi,%3B,dot,.,comma,%2C
{;keys*} ;semi=%3B;dot=.;comma=%2C

3.2.8. Form-Style Query Expansion: {?var}​

Form-style query expansion, as indicated by the question-mark ("?") operator in Level 3 and above templates, is useful for describing an entire optional query component.

For each defined variable in the variable-list:

  • append "?" to the result string if this is the first defined value or append "&" thereafter;

  • if the variable has a simple string value or no explode modifier is given, append the variable name (encoded as if it were a literal string) and an equals character ("=") to the result string; and,

  • perform variable expansion, as defined in Section 3.2.1, with the allowed characters being those in the unreserved set.

Example Template     Expansion
{?who}             ?who=fred
{?half} ?half=50%25
{?x,y} ?x=1024&y=768
{?x,y,empty} ?x=1024&y=768&empty=
{?x,y,undef} ?x=1024&y=768
{?var:3} ?var=val
{?list} ?list=red,green,blue
{?list*} ?list=red&list=green&list=blue
{?keys} ?keys=semi,%3B,dot,.,comma,%2C
{?keys*} ?semi=%3B&dot=.&comma=%2C

3.2.9. Form-Style Query Continuation: {&var}​

Form-style query continuation, as indicated by the ampersand ("&") operator in Level 3 and above templates, is useful for describing optional &name=value pairs in a template that already contains a literal query component with fixed parameters.

For each defined variable in the variable-list:

  • append "&" to the result string;

  • if the variable has a simple string value or no explode modifier is given, append the variable name (encoded as if it were a literal string) and an equals character ("=") to the result string; and,

  • perform variable expansion, as defined in Section 3.2.1, with the allowed characters being those in the unreserved set.

Example Template     Expansion
{&who}             &who=fred
{&half} &half=50%25
?fixed=yes{&x} ?fixed=yes&x=1024
{&x,y,empty} &x=1024&y=768&empty=
{&x,y,undef} &x=1024&y=768
{&var:3}           &var=val
{&list} &list=red,green,blue
{&list*} &list=red&list=green&list=blue
{&keys} &keys=semi,%3B,dot,.,comma,%2C
{&keys*} &semi=%3B&dot=.&comma=%2C