mirage / ocaml-uri

RFC3986 URI parsing library for OCaml
Other
98 stars 57 forks source link

Provide functions to put literal {";","&","="} into query strings #43

Open dsheets opened 10 years ago

dsheets commented 10 years ago

See 1ef3f1dfb41bdb4f33f223ffe16e62a33975661a which proposes also to escape !, $, and ,. Are these query string conventions scheme-specific?

edwintorok commented 9 years ago

Apparently some applications don't like having the ; encoded, for example running the URL below through Uri.of_string and Uri.to_string changes its semantics:

utop # Uri.to_string (Uri.of_string "http://repo.or.cz/w/alt-git.git?a=blob_plain;f=gitweb/README");;
- : bytes = "http://repo.or.cz/w/alt-git.git?a=blob_plain%3Bf=gitweb/README" 

The URL with %3B gives 400 - Invalid action parameter, but replacing ; with & or keeping it as ';' works:

utop # Uri.to_string (Uri.of_string "http://repo.or.cz/w/alt-git.git?a=blob_plain&f=gitweb/README");;
- : bytes = "http://repo.or.cz/w/alt-git.git?a=blob_plain&f=gitweb/README"

Perhaps Uri.to_string should have a parameter to try to keep the Uri as close as possible to its original form (if it still knows what that was).

dsheets commented 9 years ago

This is a longstanding issue which is quite simple to fix but requires breaking interface compatibility (similar to most of the other awaited changes).

Unfortunately, there is no way to retain full control over this behavior at the present time. A solution that may work for you is to use the new verbatim_query function to extract the query string as written, use Stringext.split ~on:';', use String.concat to replace ';' with '&', and then use with_query to set the query string. I realize this dance is far from ideal and I'll push some designs for the 2.0 interface which addresses this and related (#18,#43,#65) issues as soon as I can find a solid block of time.

edwintorok commented 9 years ago

Thanks, something like this worked:

match Uri.verbatim_query uri with
  | Some q ->
    Uri.with_query uri (Uri.query_of_encoded (Stringext.replace_all q ~pattern:";" ~with_:"&"))
  | None -> uri