<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-uri-template</artifactId>
<version>4.5.22</version>
</dependency> Vert.x URI Template
An implementation of the URI Template RFC.
This implements the spec level 4.
Using the URI Template
To use this component, add the following dependency to the dependencies section of your build descriptor:
-
Maven (in your
pom.xml):
-
Gradle (in your
build.gradlefile):
compile io.vertx:vertx-uri-template:4.5.22 Templates
You can create a template very easily
UriTemplate template = UriTemplate.of("http://{host}/product/{id}{?sort}"); Only a valid template can be created, any invalid template is rejected with an exception at creation time:
UriTemplate template = UriTemplate.of("{!invalid}}"); // Will throw an exception Template expansion
You can call expandToString with a list of variables to produce a valid URI string
UriTemplate template = UriTemplate.of("http://{host}/product/{id}{?sort}");
String uri = template.expandToString(Variables
.variables()
.set("host", "localhost")
.set("id", "12345")
.set("sort", "price")
); Variables holds the variables used by template expansion
-
you can set a single valued variable
variables.set("server", "localhost");
variables.set("port", "8080"); -
you can set a list valued variable
variables.set("ids", Arrays.asList("123", "456")); -
you can set a map valued variable
Map<String, String> query = new HashMap<>();
query.put("firstName", "Dale");
query.put("lastName", "Cooper");
variables.set("query", query); As seen earlier, variables are referenced within a template by their name surrounded with curly braces, e.g {host} references the host variable, this expansion is known as simple string expansion.
| There are other expansion styles, they differ from simple string expansion by their formatting and encoding. |
Lists are expanded to a comma separated value
UriTemplate template = UriTemplate.of("http://server.com/products?sort={sort}");
Variables variables = Variables.variables().set("sort", Arrays.asList("price", "name"))
assertEquals("http://server.com/products?sort=price,name", template.expandToString(variables)); Likewise, map values are expanded to comma separated values, e.g { "firstName": "Dale", "lastName": "Cooper" } expands to "firstName,Dale,lastName,Cooper" , unless they are exploded with an asterisk modifier
UriTemplate template = UriTemplate.of("http://server.com/?details={details*}");
Map<String, String> details = new HashMap<>();
details.put("firstName", "Dale");
details.put("lastName", "Cooper");
Variables variables = Variables.variables().set("details", details)
assertEquals("http://server.com/?firstName=Dale,lastName=Cooper", template.expandToString(variables)); Template encoding
Literal characters outside the reserved set and unreserved set are percent-encoded:
assertEquals("http://server.com/currency/%E2%82%AC", UriTemplate.of("http://server.com/currency/€").expandToString(variables)); Simple string expansion encodes any character outside the unreserved set to its percent-encoded equivalent:
Variables variables = Variables.variables();
variables.set("currency", "€")
assertEquals("http://server.com/currency/%E2%82%AC", UriTemplate.of("http://server.com/currency/{currency}").expandToString(variables)); Expansion styles
Beyond simple string expansion, you can use other expansion styles, expansion follows the syntax '{' operator? varname '}'.
Simple string expansion
The default expansion style when no operator is given.
-
Syntax:
{varname} -
Allowed characters: unreserved set
| Vars | Template | URI |
|---|---|---|
{ "who": "fred" } | {who} | fred |
{ "unreserved": "_" } | {unreserved} | _ |
{ "reserved": "/" } | {reserved} | %2F |
{ "pct_encoded": "%2F" } | {pct_encoded} | %252F |
{ "x": "1024", "y" : "768" } | {x,y} | 1024/y768 |
{ "list": [ "red", "green", "blue" ] } | {list} | red,green,blue |
{ "list": [ "red", "green", "blue" ] } | {list*} | red,green,blue |
{ "map": { "firstName": "Dale", "lastName": "Cooper" } } | {map} | firstName,Dale,lastName,Cooper |
{ "map": { "firstName": "Dale", "lastName": "Cooper" } } | {map*} | firstName=Dale,lastName=Cooper |
Path segment expansion
Path segment expansion is useful for creating hierarchical URI path.
-
Syntax:
{/varname} -
Allowed characters: unreserved set
| Vars | Template | URI |
|---|---|---|
{ "who": "fred" } | {/who} | /fred |
{ "unreserved": "_" } | {/unreserved} | /_ |
{ "reserved": "/" } | {/reserved} | /%2F |
{ "pct_encoded": "%2F" } | {/pct_encoded} | /%252F |
{ "x": "1024", "y" : "768" } | {/x,y} | /1024/y768 |
{ "list": [ "red", "green", "blue" ] } | {/list} | /red,green,blue |
{ "list": [ "red", "green", "blue" ] } | {/list*} | /red/green/blue |
{ "map": { "firstName": "Dale", "lastName": "Cooper" } } | {/map} | /firstName,Dale,lastName,Cooper |
{ "map": { "firstName": "Dale", "lastName": "Cooper" } } | {/map*} | /firstName=Dale/lastName=Cooper |
Form-style query expansion
Form-style query expansion is useful for creating query strings.
-
Syntax:
{?varname} -
Allowed characters: unreserved set
| Vars | Template | URI |
|---|---|---|
{ "who": "fred" } | {?who} | ?who=fred |
{ "unreserved": "_" } | {?unreserved} | ?unreserved=_ |
{ "reserved": "/" } | {?reserved} | ?reserved=%2F |
{ "pct_encoded": "%2F" } | {?pct_encoded} | ?pct_encoded=%252F |
{ "x": "1024", "y" : "768" } | {?x,y} | ?x=1024&y768 |
{ "list": [ "red", "green", "blue" ] } | {?list} | ?list=red,green,blue |
{ "list": [ "red", "green", "blue" ] } | {?list*} | ?list=red&list=green&list=blue |
{ "map": { "firstName": "Dale", "lastName": "Cooper" } } | {?map} | ?map=firstName,Dale,lastName,Cooper |
{ "map": { "firstName": "Dale", "lastName": "Cooper" } } | {?map*} | ?firstName=Dale&lastName=Cooper |
Form-style query continuation
Form-style query continuation is useful for appending to query strings.
-
Syntax:
{&varname} -
Allowed characters: unreserved set
| Vars | Template | URI |
|---|---|---|
{ "who": "fred" } | {&who} | &who=fred |
{ "unreserved": "_" } | {&unreserved} | &unreserved=_ |
{ "reserved": "/" } | {&reserved} | &reserved=%2F |
{ "pct_encoded": "%2F" } | {&pct_encoded} | &pct_encoded=%252F |
{ "x": "1024", "y" : "768" } | {&x,y} | &x=1024&y768 |
{ "list": [ "red", "green", "blue" ] } | {&list} | &list=red,green,blue |
{ "list": [ "red", "green", "blue" ] } | {&list*} | &list=red&list=green&list=blue |
{ "map": { "firstName": "Dale", "lastName": "Cooper" } } | {&map} | &map=firstName,Dale,lastName,Cooper |
{ "map": { "firstName": "Dale", "lastName": "Cooper" } } | {&map*} | &firstName=Dale&lastName=Cooper |
Reserved expansion
Extends the allowed character set of the simple string expansion to the reserved set and pct-encoded sequences.
-
Syntax:
{+varname} -
Allowed characters: unreserved set, unreserved set and pct-encoded sequence.
| Vars | Template | URI |
|---|---|---|
{ "who": "fred" } | {+who} | fred |
{ "unreserved": "_" } | {+unreserved} | _ |
{ "reserved": "/" } | {+reserved} | / |
{ "pct_encoded": "%2F" } | {+pct_encoded} | %2F |
{ "x": "1024", "y" : "768" } | {+x,y} | 1024,y768 |
{ "list": [ "red", "green", "blue" ] } | {+list} | red,green,blue |
{ "list": [ "red", "green", "blue" ] } | {+list*} | red,green,blue |
{ "map": { "firstName": "Dale", "lastName": "Cooper" } } | {+map} | firstName,Dale,lastName,Cooper |
{ "map": { "firstName": "Dale", "lastName": "Cooper" } } | {+map*} | firstName=Dale,lastName=Cooper |
Fragment expansion
Like the reserved expansion prefixed by #.
-
Syntax:
{#varname} -
Allowed characters: unreserved set, unreserved set and pct-encoded
| Vars | Template | URI |
|---|---|---|
{ "who": "fred" } | {#who} | #fred |
{ "unreserved": "_" } | {#unreserved} | #_ |
{ "reserved": "/" } | {#reserved} | #/ |
{ "pct_encoded": "%2F" } | {#pct_encoded} | #%2F |
{ "x": "1024", "y" : "768" } | {#x,y} | #1024,y768 |
{ "list": [ "red", "green", "blue" ] } | {#list} | #red,green,blue |
{ "list": [ "red", "green", "blue" ] } | {#list*} | #red,green,blue |
{ "map": { "firstName": "Dale", "lastName": "Cooper" } } | {#map} | #firstName,Dale,lastName,Cooper |
{ "map": { "firstName": "Dale", "lastName": "Cooper" } } | {#map*} | #firstName=Dale,lastName=Cooper |
Label expansion with Dot-Prefix
-
Syntax:
{.varname} -
Allowed characters: unreserved set
| Vars | Template | URI |
|---|---|---|
{ "who": "fred" } | {.who} | .fred |
{ "unreserved": "_" } | {.unreserved} | ._ |
{ "reserved": "/" } | {.reserved} | .%2F |
{ "pct_encoded": "%2F" } | {.pct_encoded} | .%252F |
{ "x": "1024", "y" : "768" } | {.x,y} | .1024.y768 |
{ "list": [ "red", "green", "blue" ] } | {.list} | .red,green,blue |
{ "list": [ "red", "green", "blue" ] } | {.list*} | .red.green.blue |
{ "map": { "firstName": "Dale", "lastName": "Cooper" } } | {.map} | .firstName,Dale,lastName,Cooper |
{ "map": { "firstName": "Dale", "lastName": "Cooper" } } | {.map*} | .firstName=Dale.lastName=Cooper |
Path-Style Parameter Expansion
-
Syntax:
{.varname} -
Allowed characters: unreserved set
| Vars | Template | URI |
|---|---|---|
{ "who": "fred" } | {;who} | ;who=fred |
{ "unreserved": "_" } | {;unreserved} | ;unreserved=_ |
{ "reserved": "/" } | {;reserved} | ;reserved=%2F |
{ "pct_encoded": "%2F" } | {;pct_encoded} | ;pct_encoded=%252F |
{ "x": "1024", "y" : "768" } | {;x,y} | ;x=1024;y=y768 |
{ "list": [ "red", "green", "blue" ] } | {;list} | ;list=red,green,blue |
{ "list": [ "red", "green", "blue" ] } | {;list*} | ;list=red;list=green;list=blue |
{ "map": { "firstName": "Dale", "lastName": "Cooper" } } | {;map} | ;map=firstName,Dale,lastName,Cooper |
{ "map": { "firstName": "Dale", "lastName": "Cooper" } } | {;map*} | ;firstName=Dale;lastName=Cooper |
Characters set cheatsheet
Reserved set
!*'();:@&=+$,/?#[]
Unreserved set
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~