How to build a relative URL securely?

1

A method takes snippets of a URL and needs to concatenate them coherently, but without presupposing details about each.

Examples:

http://server + /path + /resource.js   => http://server/path/resource.js
http://server/ + /path/ + /resource.js => http://server/path/resource.js        
http://server + path + resource.js     => http://server/path/resource.js
//server + path + resource.js          => //server/path/resource.js

Basically, the consistency is in leaving only a / bar between each element and not changing the structure of the URL as a whole, as in the last example where the protocols remain missing.

My first approach was simply to create a routine that joins two parts by checking the bars:

String joinUrlSafely(final String s1, final String s2) {
    final boolean s1HasSlash = s1.endsWith("/");
    final boolean s2HasSlash = s2.startsWith("/");
    if (s1HasSlash && s2HasSlash) {
        return s1 + s2.substring(1); //os dois tem barra, remove uma
    } else if (!s1HasSlash && !s2HasSlash) {
        return s1 + "/" + s2; //nenhum tem barra, coloca uma
    } else {
        return s1 + d2; //um dos dois tem barra, deixa ela lá
    }
}

However, I was not satisfied and the question remains:

  

Is there any API in Java or some commonly used library (Apache, Guava, ...) that does this in a more secure and standardized way? Some kind of UrlBuilder ?

    
asked by anonymous 02.02.2016 / 02:49

1 answer

1

You can use the Java API itself: java.net.URI e java.net.URL .

@Test
public void urlTest() throws URISyntaxException, MalformedURLException {
    String base = "http://server///";
    String p1 = "/path/";
    String r1 = "/resource.js";
    String newUri = concat(base, p1);

    assertEquals("http://server/path/", newUri);
    assertEquals("http://server/path/resource.js", concat(newUri, r1));

}
private String concat(String s1, String s2) throws URISyntaxException, MalformedURLException {
    URL url = new URL(s1);
    return new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile()+s2).toURI().normalize().toString();
}

Take a look at this post . EDIT

Another way is to always concatenate a "/" before each String and then before returning the value remove the duplicate "/" with a regular expression. So it saves some ifs.

url.replaceAll("(?<!(http:|https:))[//]+", "/");
    
02.02.2016 / 04:04