This is just a follow-up to say that i had used a workaround suggested by David Sheets to resolve my issue with Uri.
The Google Distance Matrix API service works when Uri replaces the pipe characters with %7C.
Since creating a request to API involves a rather inconvenient concatenating of the arguments, i have made a suggestion to https://github.com/avsm/ocaml-uri/issues/28 that an optional ~sep argument is introduced to Uri functions, like the one in Jane Street’s Core.String.concat.

Many thanks, Ollie

Begin forwarded message:

From: Ollie Frolovs <of12343@my.bristol.ac.uk>
Subject: Re: [Caml-list] Using Uri with Google Distance Matrix API
Date: 29 October 2013 11:51:13 GMT
To: David Sheets <sheets@alum.mit.edu>


On 28 Oct 2013, at 22:26, David Sheets <sheets@alum.mit.edu> wrote:

On Mon, Oct 28, 2013 at 9:58 PM, O Frolovs
<ollie.frolovs.2012@my.bristol.ac.uk> wrote:
Hello

Hi Ollie,
Hi David


I'm learning OCaml and currently trying to use it for my project at uni.

Specifically, i’m trying to use Uri [1] to create a Google Distance
Matrix request and i find it a bit awkward since the API uses pipe
character "|" for separating parameter values but Uri uses commas ","
and i could not find a way to override it:

Unfortunately, the Google Distance Matrix API does not conform to the
Internet Standard for URIs. Specifically, the pipe character "|" is
not allowed in a well-formed URI. I'm not sure why Google has decided
to use this character out of the very many separators available to
them.

This is very odd, indeed.


utop # open Core.Std;;
utop # #require "uri";;

utop # let x = Uri.of_string "http://www.github.com/";;
val x : Uri.t = <abstr>

utop # let y = Uri.add_query_param x ("origins", ["Bristol";
"Cambridge"; "Plymouth"; "London"]);;
val y : Uri.t = <abstr>

utop # Uri.to_string y;;
- : string = "http://www.github.com/?origins=Bristol,Cambridge,Plymouth,London"

This is not what the API expects.

I also tried concatenating the origins values before passing it to Uri
but as you can see below, Uri performed character escape on pipe
characters. So besides not looking elegant, it did not work:

utop # String.concat ~sep:"|" ["Bristol"; "Cambridge"; "Plymouth"; "London"];;
- : string = "Bristol|Cambridge|Plymouth|London"

utop # let y = Uri.add_query_param x ("origins", [c]);;
val y : Uri.t = <abstr>

utop # Uri.to_string y;;
- : string = "http://www.github.com/?origins=Bristol%7CCambridge%7CPlymouth%7CLondon"

I am wondering

(a) if there is a way to make Uri do what i want, that is to use pipe
character to separate the origins values.

I do not believe there is a way to accomplish this in Uri 1.3.8. Have
you tried submitting the percent-encoded query string to the API to
see if Google properly interprets the escaping of invalid characters?

I just tried this and it worked! Thanks for the suggestion.

Uri is designed to take as input any string and produce as output only
those strings that are conformant to RFC 3986.

(b) why Uri does not have an optional ~sep parameter, like Jane
Street's Core.String.concat does?

No one has implemented it yet. :-) There has been discussion about
significantly changing this API feature for 1.4 as well.

If you are not manipulating the URIs heavily and are not in need of
input sanitation, using Uri may not be necessary unless another
library requires input of Uri.t values.
I am using LWT and Cohttp which i believe requires Uri.t. 
So i am very happy the escaping worked with the API :)

If none of this helps you, please create an issue at
<https://github.com/mirage/ocaml-uri/issues?state=open> and we may end
up adding something to help you in the next revision (could be later
this week depending on how persuasive you are and how extensive the
feature).
I will. I think the question here is how ‘real-world’ the Uri library wants to be.
As an example – I do not know much about JSON yet, but i would expect
JSON libraries to make compromises to work with the real web services.
Otherwise, what good is the library if it only works with carefully chosen
artificial examples, RFC-compliant or not.

Hope this helps,
It helped a lot, thanks again! :)

Regards,
Ollie