diff options
author | adamw <adam@warski.org> | 2017-08-02 14:02:13 +0200 |
---|---|---|
committer | adamw <adam@warski.org> | 2017-08-02 14:02:13 +0200 |
commit | 4fd5b1570c006a7ad5e022cadb9f41decf51d866 (patch) | |
tree | dc1b2fc77e622ca14b8278e54d4a3ad73aaeb71c | |
parent | e96f63034fbc0bb2c41550ddf7b37ed5ba6b89b2 (diff) | |
download | sttp-4fd5b1570c006a7ad5e022cadb9f41decf51d866.tar.gz sttp-4fd5b1570c006a7ad5e022cadb9f41decf51d866.tar.bz2 sttp-4fd5b1570c006a7ad5e022cadb9f41decf51d866.zip |
Special encoding for fragment
-rw-r--r-- | core/src/main/scala/com/softwaremill/sttp/Uri.scala | 29 | ||||
-rw-r--r-- | core/src/test/scala/com/softwaremill/sttp/UriTests.scala | 4 |
2 files changed, 23 insertions, 10 deletions
diff --git a/core/src/main/scala/com/softwaremill/sttp/Uri.scala b/core/src/main/scala/com/softwaremill/sttp/Uri.scala index f66793a..ce758a1 100644 --- a/core/src/main/scala/com/softwaremill/sttp/Uri.scala +++ b/core/src/main/scala/com/softwaremill/sttp/Uri.scala @@ -123,7 +123,7 @@ case class Uri(scheme: String, val queryS = encodeQueryFragments(queryFragments.toList, previousWasPlain = true, new StringBuilder()) - val fragS = fragment.fold("")("#" + _) + val fragS = fragment.fold("")("#" + encodeFragment(_)) s"$schemeS://$userInfoS$hostS$portS$pathPrefixS$pathS$queryPrefixS$queryS$fragS" } @@ -139,19 +139,30 @@ case class Uri(scheme: String, else URLEncoder.encode(String.valueOf(s), "UTF-8") - private val relaxedQueryAllowedCharacters = { - // https://stackoverflow.com/questions/2322764/what-characters-must-be-escaped-in-an-http-query-string - val alphanum = (('a' to 'z') ++ ('A' to 'Z') ++ ('0' to '9')).toSet - val special = Set('/', '?', ':', '@', '-', '.', '_', '~', '!', '$', '&', - '\'', '(', ')', '*', '+', ',', ';', '=') - alphanum ++ special + private object Rfc3986 { + val AlphaNum: Set[Char] = + (('a' to 'z') ++ ('A' to 'Z') ++ ('0' to '9')).toSet + val Unreserved: Set[Char] = AlphaNum ++ Set('-', '.', '_', '~') + val SubDelims: Set[Char] = + Set('!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '=') + val PChar: Set[Char] = Unreserved ++ SubDelims ++ Set(':', '@') + val Query: Set[Char] = PChar ++ Set('/', '?') + val Fragment: Set[Char] = Query } - private def encodeQueryRelaxed(s: String): String = { + // https://stackoverflow.com/questions/2322764/what-characters-must-be-escaped-in-an-http-query-string + private def encodeQueryRelaxed(s: String): String = + encode(s, Rfc3986.Query) + + // https://stackoverflow.com/questions/2053132/is-a-colon-safe-for-friendly-url-use/2053640#2053640 + private def encodeFragment(s: String): String = + encode(s, Rfc3986.Fragment) + + private def encode(s: String, allowedCharacters: Set[Char]): String = { val sb = new StringBuilder() // based on https://gist.github.com/teigen/5865923 for (c <- s) { - if (relaxedQueryAllowedCharacters(c)) sb.append(c) + if (allowedCharacters(c)) sb.append(c) else { for (b <- c.toString.getBytes("UTF-8")) { sb.append("%") diff --git a/core/src/test/scala/com/softwaremill/sttp/UriTests.scala b/core/src/test/scala/com/softwaremill/sttp/UriTests.scala index 26e7936..fb55468 100644 --- a/core/src/test/scala/com/softwaremill/sttp/UriTests.scala +++ b/core/src/test/scala/com/softwaremill/sttp/UriTests.scala @@ -39,7 +39,9 @@ class UriTests extends FunSuite with Matchers { Nil, Nil, None) -> - "http://us%26er:pa%20ss@example.com" + "http://us%26er:pa%20ss@example.com", + Uri("http", None, "example.com", None, Nil, Nil, Some("f:g/h i")) -> + "http://example.com#f:g/h%20i", ) for { |