Based on the answer by Yann Simon, here is a simple CORS proxy implementation that allows you to transfer downloaded remote files and transfer them to the client. It does not load the entire file into memory.
import play.api.libs.iteratee._ private def getAndForwardStream(requestHolder: WSRequestHolder)(computeHeaders: ResponseHeaders => ResponseHeader): Future[SimpleResult] = { val resultPromise = scala.concurrent.Promise[SimpleResult] requestHolder.get { wsResponseHeaders: ResponseHeaders => val (wsResponseIteratee, wsResponseEnumerator) = Concurrent.joined[Array[Byte]] val result = SimpleResult( header = computeHeaders(wsResponseHeaders), body = wsResponseEnumerator ) resultPromise.success(result) wsResponseIteratee } resultPromise.future } def corsProxy(url: URL) = Action.async { implicit request => val requestHolder = WS.url(url.toString).withRequestTimeout(10000) getAndForwardStream(requestHolder) { wsResponseHeaders: ResponseHeaders =>
The important part here is the use of play.api.libs.iteratee.Concurrent.joined[Array[Byte]] . It allows you to create an Iteratee / Enumerator pair, so whenever you add bytes to Iteratee, these bytes will be enumerated by an enumerator.
This was the missing item because:
- You need Iteratee to use the WS answer.
- You need an Enumerator to create a response in the game.
source share