Permalink
Browse files

! http: introduce a distinction between "?key=" and "?key" in queries,

…fixes #460

The breaking change is that a parse/render round-trip will reproduce a
trailing '=' if the value is empty as well as no trailing '=' if it was
originally missing.

Also, the default behavior was changed so that '=' is always rendered even
for empty values unless you use the special value `Query.EmptyValue`.
  • Loading branch information...
jrudolph committed Sep 26, 2013
1 parent 80e59e1 commit d2b8bba5e6870f1a75c2a7d10bca446aa3b484fd
@@ -438,7 +438,8 @@ object Uri {
case Query.Cons(key, value, tail)
if (q ne this) r ~~ '&'
enc(key)
- if (!value.isEmpty) { r ~~ '='; enc(value) }
+ if (value ne Query.EmptyValue) r ~~ '='
+ enc(value)
append(tail)
case Query.Raw(value) r ~~ value
}
@@ -447,6 +448,9 @@ object Uri {
override def newBuilder: mutable.Builder[(String, String), Query] = Query.newBuilder
}
object Query {
+ /** A special empty String value which will be rendered without a '=' after the key. */
+ val EmptyValue: String = new String(Array.empty[Char])
+
/**
* Parses the given String into a Query instance.
* Note that this method will never return Query.Empty, even for the empty String.
@@ -302,7 +302,7 @@ private[http] class UriParser(input: ParserInput, charset: Charset, mode: Uri.Pa
// putting some pressure onto the JVM stack
def readKVP(): Query = {
val key = part
- val value = if (ch('=')) part else ""
+ val value = if (ch('=')) part else Query.EmptyValue
val tail = if (ch('&')) readKVP() else Query.Empty
Query.Cons(key, value, tail)
}
@@ -361,8 +361,8 @@ class UriSpec extends Specification {
// queries
normalize("?") === "?"
normalize("?key") === "?key"
- normalize("?key=") === "?key" // our query model cannot discriminate between these two inputs
- normalize("?key=&a=b") === "?key&a=b" // our query model cannot discriminate between these two inputs
+ normalize("?key=") === "?key="
+ normalize("?key=&a=b") === "?key=&a=b"
normalize("?key={}&a=[]") === "?key=%7B%7D&a=%5B%5D"
normalize("?key={}&a=[]", mode = Uri.ParsingMode.Strict) must throwAn[IllegalUriException]
normalize("?=value") === "?=value"
@@ -45,8 +45,8 @@ class BasicMarshallersSpec extends Specification {
"The FormDataMarshaller" should {
"properly marshal FormData instances to application/x-www-form-urlencoded entity bodies" in {
marshal(FormData(Map("name" -> "Bob", "pass" -> "hällo", "admin" -> ""))) ===
- Right(HttpEntity(ContentType(`application/x-www-form-urlencoded`, `UTF-8`), "name=Bob&pass=h%E4llo&admin"))
+ Right(HttpEntity(ContentType(`application/x-www-form-urlencoded`, `UTF-8`), "name=Bob&pass=h%E4llo&admin="))
}
}
-}
+}

0 comments on commit d2b8bba

Please sign in to comment.