124

How do I build a URL or a URI in Java? Is there an idiomatic way, or libraries that easily do this?

I need to allow starting from a request string, parse/change various URL parts (scheme, host, path, query string) and support adding and automatically encoding query parameters.

Barett
  • 5,826
  • 6
  • 51
  • 55
jon077
  • 10,303
  • 11
  • 39
  • 37
  • 7
    Upvoting the question long after it is closed because it is not clear whether a popular non-deprecated solution to this problem exists. I found this by googling for 'java URL parameter class'. – user1445967 Aug 12 '13 at 00:12
  • 4
    My intent was to find a URL builder for Java, and this question is useful for me at least. – whirlwin Oct 07 '15 at 13:44

8 Answers8

80

As of Apache HTTP Component HttpClient 4.1.3, from the official tutorial:

public class HttpClientTest {
public static void main(String[] args) throws URISyntaxException {
    List<NameValuePair> qparams = new ArrayList<NameValuePair>();
    qparams.add(new BasicNameValuePair("q", "httpclient"));
    qparams.add(new BasicNameValuePair("btnG", "Google Search"));
    qparams.add(new BasicNameValuePair("aq", "f"));
    qparams.add(new BasicNameValuePair("oq", null));
    URI uri = URIUtils.createURI("http", "www.google.com", -1, "/search",
                                 URLEncodedUtils.format(qparams, "UTF-8"), null);
    HttpGet httpget = new HttpGet(uri);
    System.out.println(httpget.getURI());
    //http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq=
}
}

Edit: as of v4.2 URIUtils.createURI() has been deprecated in favor of URIBuilder:

URI uri = new URIBuilder()
        .setScheme("http")
        .setHost("www.google.com")
        .setPath("/search")
        .setParameter("q", "httpclient")
        .setParameter("btnG", "Google Search")
        .setParameter("aq", "f")
        .setParameter("oq", "")
        .build();
HttpGet httpget = new HttpGet(uri);
System.out.println(httpget.getURI());
Chin
  • 19,717
  • 37
  • 107
  • 164
Chikei
  • 2,104
  • 1
  • 17
  • 21
  • 20
    This works, but as of v4.2 URIUtils.createURI() has been deprecated in favor of URIBuilder. On the positive side this URIBuilder seems to have an addParameter() method so building request strings should at least be simpler now. – stian Oct 30 '12 at 12:21
  • 6
    `URIBuilder builder = new URIBuilder() .setScheme("http") .setHost("www.google.com") .setParameters(qparams);` as @stian said – vanduc1102 Mar 27 '15 at 09:32
  • Println above prints the following; http://www.google.com/search?q=httpclient&btnG=Google+Search&aq=f&oq= – Berkan Ercan May 04 '17 at 11:39
  • tutorial link is broken – Alex Apr 20 '21 at 13:47
  • How to set path when multiple paths are to be given? For eg. "https://localhost/api/customer" + "/" +{Id1} + "/" + "summary?invoiceId=" + {Id2} + "&page=0&pageSize=10&q=" + {Id3}; – Dhruv Bhatnagar Jul 10 '21 at 21:58
  • HC v5 has the same functionality but the class is now part of the httpcomponents-core library – Zac Thompson Mar 17 '23 at 16:05
65

As the author, I'm probably not the best person to judge if my URL/URI builder is good, but here it nevertheless is: https://github.com/mikaelhg/urlbuilder

I wanted the simplest possible complete solution with zero dependencies outside the JDK, so I had to roll my own.

Mikael Gueck
  • 5,511
  • 1
  • 27
  • 25
  • 6
    It looks great Mikael, have you thought of publishing it to maven central? I know its small but makes using it easier. I can't find a similar class besides in JAX-RS. The lack of dependencies is definitely a plus. – Barry Pitman Mar 01 '12 at 08:46
  • It looks nice, but since it's a builder and thus mutable, why are there setters only for parameters, but not for host, port, protocol and path? And, well, no getters for those also. UPD: Oh, it's not mutable - setParameter creates a clone. Well, still setHost/setPort/... could work same way. Or, perhaps, a mutable version would be nice to have too. – mvmn Jun 01 '13 at 01:15
  • 3
    "simplest possible complete solution with zero dependencies" - Sounds like you know what is important! Your answer should be the accepted one imho. Including all of HttpClient (with all it's version updates and even deprecating the very API this question is about) just for building a url is what makes for top-heavy bug-riddled apps. – Stijn de Witt Nov 28 '13 at 19:48
  • 4
    Finally on Maven Central, and it only took me four years to get done. – Mikael Gueck Mar 20 '16 at 09:14
  • @mikaelhg Thank you! I need exactly in this moment! – Fabian Damken May 06 '16 at 17:41
  • I found this not suitable for my purposes as it creates a new instance whenever a parameter is changed. I want to be able to call builder.addParameter() in an if clause without having to set the variable to it. Is just ugly imho. – CrushedPixel Jul 03 '16 at 22:46
56

Apache HTTPClient?

takete.dk
  • 2,705
  • 1
  • 19
  • 12
  • As of Jun 2015: http://hc.apache.org/httpcomponents-client-ga/tutorial/html/fundamentals.html#d5e49 – arun Jun 17 '15 at 23:36
29

Using HTTPClient worked well.

protected static String createUrl(List<NameValuePair> pairs) throws URIException{

  HttpMethod method = new GetMethod("http://example.org");
  method.setQueryString(pairs.toArray(new NameValuePair[]{}));

  return method.getURI().getEscapedURI();

}
Michael Myers
  • 188,989
  • 46
  • 291
  • 292
jon077
  • 10,303
  • 11
  • 39
  • 37
  • 7
    This is now deprecated functionality. Does anyone know how to use the new HTTP Components package to do the same because it's stumped me. – Link19 Feb 29 '12 at 10:42
  • 3
    The new 4x version does not support this any more. – Joscha Jun 15 '12 at 21:26
17

There are plenty of libraries that can help you with URI building (don't reinvent the wheel). Here are three to get you started:


Java EE 7

import javax.ws.rs.core.UriBuilder;
...
return UriBuilder.fromUri(url).queryParam(key, value).build();

org.apache.httpcomponents:httpclient:4.5.2

import org.apache.http.client.utils.URIBuilder;
...
return new URIBuilder(url).addParameter(key, value).build();

org.springframework:spring-web:4.2.5.RELEASE

import org.springframework.web.util.UriComponentsBuilder;
...
return UriComponentsBuilder.fromUriString(url).queryParam(key, value).build().toUri();

See also: GIST > URI Builder Tests

Nick Grealy
  • 24,216
  • 9
  • 104
  • 119
  • 3
    EE 7 is the correct answer. All you have to do is pull in the entire suite of EE libraries, choose a JAX-RS implementation, resolve jax-rs version conflicts, and as a reward you'll have a handy UriBuilder class that works really well. Sarcasm aside, this *is* the correct answer. :) – tekHedd Mar 12 '19 at 19:36
  • 1
    As of Spring 5 check out `UriBuilder` (https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/util/UriBuilder.html) and `UriBuilderFactory` (https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/util/UriBuilderFactory.html) – Brice Roncace Jan 14 '20 at 23:13
15

Use OkHttp

It's 2022 and there is a very popular library named OkHttp which has been starred 41K times on GitHub. With this library, you can build an url like below:

import okhttp3.HttpUrl;

URL url = new HttpUrl.Builder()
    .scheme("http")
    .host("example.com")
    .port(4567)
    .addPathSegments("foldername/1234")
    .addQueryParameter("abc", "xyz")
    .build().url();
Tyler Liu
  • 19,552
  • 11
  • 100
  • 84
  • I fixed a typo, it's `addPathSegment` (not `addPathSegments`). – PapaFreud Aug 30 '19 at 06:19
  • @PapaFreud both exist for different reason, reverted the fix. – Saikat Aug 11 '21 at 05:11
  • 1
    If you're using OkHttp in your project anyway, then there is nothing wrong with this approach. However, if all you really need is a way to build URLs, I would doubt that pulling in a 770 kB JAR is the way to go. – Robert Strauch Mar 18 '22 at 08:05
  • 1
    @RobertStrauch I get your point. But it really depends. Not all applications are size sensitive. Pulling in a "big" jar won't make your application much slower. So the "disadvantage" is only the size and nothing else. – Tyler Liu Mar 19 '22 at 17:31
  • @TylerLiu I agree on that. The context for e.g. a mobile application is much different to some internal "enterprise" application. When in doubt, I personally favor the approach https://youmightnotneed.com is taking, though this affects the world of JavaScript. I first check which libraries the project is already using before pulling in further libs or write helpers on my own. – Robert Strauch Mar 20 '22 at 18:25
1

After being lambasted for suggesting the URL class. I will take the commenter's advice and suggest the URI class instead. I suggest you look closely at the constructors for a URI as the class is very immutable once created.
I think this constructor allows you to set everything in the URI that you could need.

URI(String scheme, String userInfo, String host, int port, String path, String query, String fragment)
          Constructs a hierarchical URI from the given components.
Mike Pone
  • 18,705
  • 13
  • 53
  • 68
  • 8
    But it doesn't provide functionality to actually construct and encode a query string from a set of name value pairs. – Link19 Mar 02 '12 at 11:52
  • 4
    As the child prodigy said to Alan Partridge - one cannot have degradations of immutability, it either is or it isn't ;-) http://www.youtube.com/watch?v=_lvFns5Lubc – Stewart Jan 02 '13 at 22:25
  • URI's constructor does nasty things to the path. See http://blog.palominolabs.com/2013/10/03/creating-urls-correctly-and-safely/ for the details. – mpierce Oct 04 '13 at 17:00
  • 1
    Let this answer stand as an example of how NOT to do this then. – Mike Pone Oct 04 '13 at 20:59
  • 1
    String query... Thanks Sun/Oracle for the granularity. We will just replace all spaces with plus symbols, uri-encode all the parameters and link them all together with ampersand symbols ourselves then... *bangs head on table repeatedly* – Stijn de Witt Nov 28 '13 at 19:56
0

You can use the URIBuilder class included in Apache HTTPComponents Core5: import org.apache.httpcomponents.core5:httpcore5:5.2.1, then:

URI uri = new URIBuilder("http://yourapi.com/rest")
        .addParameter("count", "5")
        .addParameter("filter", "full text search")
        .build();

The httpcore5 has no dependencies but it's a 900kb jar file. If size matters, you can use this library instead: https://gitlab.com/mvysny/apache-uribuilder - I've only copied the URIBuilder out of httpcore5 and published the jar on Maven Central; the jar is 33kb.

Martin Vysny
  • 3,088
  • 28
  • 39