java.net.URI#toASCIIString
to the rescue.
From the documentation
Returns the content of this URI as a string.
If this URI was created by invoking one of the constructors in this class then a string equivalent to the original input string, or to the string computed from the originally-given components, as appropriate, is returned. Otherwise this URI was created by normalization, resolution, or relativization, and so a string is constructed from this URI's components according to the rules specified in RFC 2396, section 5.2, step 7.
So your code becomes
def getProductPage(slug: String, locale: String) = AsyncAction {
flow {
val response = gateway.getPathBySlug(slug, locale).!
val url = (response.json \ "url").as[String]
val encodedDestination = new URI(url).toASCIIString
MovedPermanently(encodedDestination)
} recover {
case ex => throw ex
}
}