Guava: Include a new, useful URI class

Created on 31 Oct 2014  路  19Comments  路  Source: google/guava

_Original issue created by [email protected] on 2012-05-16 at 07:51 PM_


The problem with Java is it lacks a URI class that can manipulate query parameters properly.

P4 package=net status=research type=addition

Most helpful comment

The WHATWG spec is the best yet, but it's still not exactly consistent with what the browsers do. And the browsers themselves aren't consistent with each other. I ended up doing a lot of research, including this:
https://docs.google.com/spreadsheets/d/1BgGAhJ5WE3JBsATeudamiBzxmgEhwkfcFqQmPx8qrkc/edit#gid=0

All 19 comments

_Original comment posted by [email protected] on 2012-05-16 at 07:51 PM_


cgdecker: "I have wished that there were a better way of building URIs."

_Original comment posted by ullenboom on 2012-05-18 at 02:11 PM_


Enterprise developers can use the new Jersey 2.0 API. Take a look at http://jax-rs-spec.java.net/nonav/2.0-SNAPSHOT/apidocs/javax/ws/rs/core/UriBuilder.html. Jersey is the JAX-RS 2.0 RI and JAX-RS will be part of Java EE 7. Then there will be some kind of URI-manipulating API.

_Original comment posted by [email protected] on 2012-06-19 at 05:28 PM_


We want to do this, but there are numerous challenges.


Status: Accepted
Labels: Type-Addition, Package-Net

_Original comment posted by [email protected] on 2012-11-07 at 07:42 PM_


_(No comment entered for this change.)_


Blocking: #1191

_Original comment posted by amertum on 2013-01-24 at 12:24 PM_


Maybe you can provide different tools which integrate easily with different apps.

For example, we need a query param handler to do something like :

QueryParams.from(Map<String, String[]>).get("param").firstOr("defaultValue");
QueryParams.from(Map<String, String[]>).get("param").firstAsIntOr(5);
QueryParams.from(Map<String, String[]>).get("param").allOr("value1", "value2");
QueryParams.from(Map<String, String[]>).get("param").allAsIntOr(1, 2);

I like this idea. Any thoughts on an API?

FYI, we're doing this in OkHttp. I'm hoping to get something that solves most HTTP use cases, including IDNs.
https://github.com/square/okhttp/issues/1486

Maybe a good place to start is the target spec. RFCs 2396 and 3986 are good candidates. Android's Uri and Java's URI do 2396. However 3986 is listed as obsoleting 2396.

Whatwg has a spec for URLs, which I think Jesse is targeting in OkHTTP.

Thoughts?

The WHATWG spec is the best yet, but it's still not exactly consistent with what the browsers do. And the browsers themselves aren't consistent with each other. I ended up doing a lot of research, including this:
https://docs.google.com/spreadsheets/d/1BgGAhJ5WE3JBsATeudamiBzxmgEhwkfcFqQmPx8qrkc/edit#gid=0

Wow, that spreadsheet is terrifying! Well, given the multitude of specs and inconsistent behavior, maybe it's wise to divide the problem:

  • Allow different types of URIs by creating a base Uri that's intended to be extended.
  • Support additional specs by isolating encoding and decoding into its own class(es).

Here's a 50Kft sketch:

/**
 * Spec independent. Can be extended for other URIs such
 * as URL, MAILTO, or LDAP.
 */
Uri
    String getScheme()
    String getAuthority()
    ...

UriBuilder<T extends Uri>
    T build();
    UriBuilder<T extends Uri> scheme(String scheme)
    UriBuilder<T extends Uri> authority(String authority)
    ...

/**
 * Spec specific.
 */
UriCodec<T extends Uri>
    T decode(String uriString)
    String encode(T uri)

Nah, my policy has been to just write one good URL that does what you want. Nobody wants to decide between Firefox parsing mode and Chrome parsing mode, they just want something that's going to work.

For example, today I'm doing the first steps towards IDNA mapping.
https://github.com/square/okhttp/pull/1612

My thought was to choose a spec - let's say 3986 - and implement that for Guava. But factor things such that it'd be easy for clients to extend for other specs and schemes.

(While I'm replying to URL threads....)

I'm pretty confident that the WHATWG spec is the only spec worth following nowadays. (One of the serious problems with common.net.Uri is that it follows RFC 3986.) And while I've only skimmed over OkHttp's HttpUrl, I predict that we're now more likely to migrate Google to it (or to some other WHATWG-based implementation, should one catch on) than to introduce our own open-source URL class. (But to throw some water on that: We're now talking a very, very small chance rather than a very, very, very small chance.)

The WHATWG spec is good, but it isn't perfect. There are a few edge cases where it disagrees with what the browsers actually do.

@swankjesse , have you spoken to the people behind the spec? From what I understand, it's still a work in progress. They'd probably be happy to hear about discrepancies, or if they're aware of them, they might be able to tell us why they exist (where there are security reasons, whether browsers have committed to change their behavior, whatever).

@cpovirk , other than following the WHATWG spec, any thoughts on what would make a good URL library? Maybe some tough learnings from the multiple implementations that you already have?

That's the big thing (and the one that makes migrating Google's own code very difficult). Aside from giving general advice like "immutability" and "builders," I glanced over our open issues. They seem to be mostly things that Jesse has covered -- for example, better accessors like pathSegments. Unless we're able to investigate a bunch of time into this (which would happen late this year at best), my plan will be "assume Jesse is right about everything" :) Sorry that I don't have anything more specific for you.

You're right - Jesse is very wise :)

google.common.net has several classes that could be used within a more general URL class (eg HostAndPort). Would you be open to additional sub-URL classes? For example: QueryParams, PathSegments, etc?

QueryParams could be a good start. If there's even a very, very, very small chance, I'd be happy to open an issue to bounce a design and, if it moves forward, write a patch.

You're all too kind. @ericedens please grab OkHttp if that's sufficient for you. If it's too much, extracting HttpUrl into its own standalone thing is also possible. Though I don't think _I'll_ do that, you're welcome to. There's been non-zero demand.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

JWT007 picture JWT007  路  4Comments

philgebhardt picture philgebhardt  路  3Comments

edwardlee03 picture edwardlee03  路  4Comments

PhilippWendler picture PhilippWendler  路  4Comments

gissuebot picture gissuebot  路  5Comments