<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-uri-template</artifactId>
<version>4.4.9</version>
</dependency>
Vert.x URI Template
An implementation of the URI Template RFC.
This implements the spec level 4.
This module has Tech Preview status, this means the API can change between versions. |
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.gradle
file):
compile io.vertx:vertx-uri-template:4.4.9
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-_.~