Skip to content

Provide explanation and proposal for enhanced URI builder

License

Notifications You must be signed in to change notification settings

intershop/poc-jdk-uri

Repository files navigation

Introduction

The content of this project is not production ready

  • The first part tries an explanation, why it's difficult to provide a correct encoded URI with JDK java.net classes.
  • The second part tries to provide a proposal for easier usage with a URI builder API.

Expected correct URI

For the given customer REST API endpoint: https://servername/rest/customers/<customer-id> I would expect the following encoded URI.

EXPECTED_URI_PATH.put("2024-1234", "https://servername/rest/customers/2024-1234");
EXPECTED_URI_PATH.put("2024/1234", "https://servername/rest/customers/2024%2F1234");
EXPECTED_URI_PATH.put("2024 1234", "https://servername/rest/customers/2024%201234");
EXPECTED_URI_PATH.put("2024+1234", "https://servername/rest/customers/2024+1234");

Correct URI Encoding with java.net?

Using java.net.URI

The test class "URITest" shows that the path elements are encoded, but the slash '/' not. What is to do, if path elements containing slashes like "customer-numbers". Patterns with slashes are common. So I could have the customer number "2024/1234" at my local town gas dealer.

URI.create("https://servername/rest").resolve(URI.create("/customers/" + customerID));

This breaks:

EXPECTED_URI_PATH.put("2024/1234", "https://servername/rest/customers/2024%2F1234");

because the result is https://servername/rest/customers/2024/1234 that is a complete different endpoint.

Using java.net.URLEncode#encode

The test class URLEncodeTest shows the common solution to encode path elements with URLEncode#encode. That leads to '+' sign in the path of the URL, which is not RFC conform. The documentation of URLEncode#encode clearly defines, that the method is valid for the query part.

Translates a string into application/ x-www-form-urlencoded
format using a specific Charset.
URI.create("https://servername/rest/customers/" + URLEncode.encode(customerID));

This breaks:

EXPECTED_URI_PATH.put("2024 1234", "https://servername/rest/customers/2024%201234");

because the result is https://servername/rest/customers/2024+1234 that could be another customer.

Workaround with java.net

URLEncode.encode doing it well, except the '+' sign encoding. And this method is available in other languages in a similar way (e.g. typescript)

URLEncoder.encode(customerID.replaceAll("\\+", "%2B"), StandardCharsets.UTF_8)
  .replaceAll("\\+", "%20").replaceAll("%252B", "+");

Proposal for URIBuilder API

Personally, I would prefer a builder pattern, where the attributes are declarative assigned.

var customerURIBuilder = URIBuilder.createURL()
                            .scheme(SCHEME)
                            .server(SERVER)
                            .pathElements("rest", "customers", "2024/1234");
URI uri = customerURIBuilder.build();

The test class URIBuilderTest contains also example for relative URLs.

var relativeAddress = URIBuilder.createRelativeURL()
                            .pathElements("addresses", "shipping address")
                            .build();

Combining both

URI addressURI = customerURIBuilder.pathElements(relativeAddress.getPathElements()).build();

The proposal is incomplete and should only explain the idea.

About

Provide explanation and proposal for enhanced URI builder

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages