Open spring-projects-issues opened 8 years ago
Rossen Stoyanchev commented
We've already looked into supporting RFC 6570. It's very extensive and arguably well beyond most needs. Even the spec recognizes that and defines itself in terms of 4 levels (section 1.2). Moreover there are significant differences in the way Spring's URI template support works and we've made a conscious decision not to change the mechanisms in place but rather evolve them as needed, i.e. not seeking compliance with the spec. You can see more comments on that.
Note that the RestTemplate does have a UriTemplateHandler extension point which allows you to completely replace the URI template handling for example swapping out our URI template support with another from an external library that supports RFC 6570.
That said we can consider specific features and enhancements around Spring's URI template handling. That would mean a separate ticket with a more specific request for enhancement.
Stefan Kühnel commented
Hello @Rossen
Stoyanchev,
thanks for the update and the links.
In the REST scenario we have we had a ressource like Customer. The URI design looks like the following (using RFC 6570 syntax), which follows common best practices from all I can tell:
https://{host}:{port}/v42/customers{/id}{?size,page,name}}
This is very similar to what Spring Data Rest does (e.g. https://spring.io/guides/gs/accessing-data-rest/), but we want some more control.
For a client side wrapper of the ressource, it could look something like the following:
public class Customers
{
private String ID_PARAM = "id";
private String SIZE_PARAM = "size";
private String PAGE_PARAM = "page";
private String NAME_PARAM = "name";
// One can easily see and understand the whole structure and design of the resouce URIs with this one line.
private String URI_TEMPLATE = "https://api.example.com/v42/customers{/id}{?size,page,name}}";
private RestTemplate template = new RestTemplate();
public List<Customer> getCustomers(int page, int size)
{
Map<String,Object> urlVariables = new HashMap<>();
urlVariables.add(PAGE_PARAM, page);
urlVariables.add(SIZE_PARAM, size);
Customer[] customers = template.getForObject(URI_TEMPLATE, Customer[].class, urlVariables);
return Arrays.asList(customers);
}
public Customer getCustomer(long id)
{
Map<String,Object> urlVariables = new HashMap<>();
urlVariables.add(ID_PARAM, id);
Customer customer = template.getForObject(URI_TEMPLATE, Customer.class, urlVariables);
return customer;
}
public List<Customer> searchCustomer(String name)
{
Map<String,Object> urlVariables = new HashMap<>();
urlVariables.add(NAME_PARAM, name);
Customer[] customers = template.getForObject(URI_TEMPLATE, Customer[].class, urlVariables);
return Arrays.asList(customers);
}
}
This looks very simple to me: Always the same URI template. The correct URI would be created "automagically" depending on the given urlVariables
.
For this to work the types as used in UriTemplate of Spring HATEOAS ("", "?", "/", "#"
) are sufficient IMHO.
Rossen Stoyanchev commented
We can consider an alternative UriTemplateHandler
that supports a limited subset of the RFC based on the given list of operators. Probably taking a similar approach as in the Spring HATEOAS UriTemplate
, resolving what variables should be added from expressions and then building the URI with UriComponentsBuilder. The main difference is that it would be packaged as a UriTemplateHandler
and available to plug into the RestTemplate
.
Stefan Kühnel commented
Thanks, Rossen, this sounds very good to me. :-)
Stefan Kühnel opened SPR-14134 and commented
org.springframework.web.util.UriTemplate and org.springframework.web.util.DefaultUriTemplateHandler (and RestTemplate as consequence) don't support the complete syntax of RfC 6570, but Spring HATEOAS has a version that does org.springframework.hateoas.UriTemplate. So the features should be merged into the "standard" template functionality.
Affects: 4.2.5
Issue Links:
15137 Support advanced URI Template Syntax ("duplicates")
17535 Support RFC 6570 style URI template encoding
1 votes, 2 watchers