I'm working with Unfiltered 0.6.8 (using the Jetty connector) and have encountered an odd behaviour: path segments aren't URL decoded.
The following bit of code is my minimal test case:
import unfiltered.request._
import unfiltered.response._
object Test extends App with unfiltered.filter.Plan {
def intent = {
case reg @ Path(Seg(test :: Nil)) =>
println(test)
ResponseString(test)
}
unfiltered.jetty.Http.local(8080).filter(Test).run()
}
Querying http://localhost:8080/some_string
yields the expected result: some_string
, both on the client and server side.
On the other hand, http://localhost:8080/some%20string
yields some%20string
on both client and server, rather than the some string
I was expecting.
Working around the issue is trivial (java.net.URLDecoder#decode(String, String)
), but I'd like to know if:
As a side note, the unfiltered
tag doesn't exist and I do not have enough reputation to create it, which is why I defaulted to scala
.
Strange, I'm seeing this behavior too. There is nothing in the Seg
object that does any sort of url decoding prior to splitting up the path segments and I don't see anything else in the framework for this either. I ran into a post that detailed a solution using a custom extractor as follows:
object Decode {
import java.net.URLDecoder
import java.nio.charset.Charset
trait Extract {
def charset: Charset
def unapply(raw: String) =
Try(URLDecoder.decode(raw, charset.name())).toOption
}
object utf8 extends Extract {
val charset = Charset.forName("utf8")
}
}
Then you could use it like this:
case reg @ Path(Seg(Decode.utf8(test) :: Nil)) =>
println(test)
ResponseString(test)
Or like this if you wanted the entire path decoded:
case reg @ Path(Decode.utf8(Seg(test :: Nil))) =>
println(test)
ResponseString(test)
Thankfully the framework is flexible and open to extension like this, so you certainly have options.