Vert.x URI Template
An implementation of the URI Template RFC.
This implements the spec level 4.
Warning
|
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
):
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-uri-template</artifactId>
<version>4.3.8</version>
</dependency>
-
Gradle (in your
build.gradle
file):
compile io.vertx:vertx-uri-template:4.3.8
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.
Note
|
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 |