-
-
Save brikis98/5582159 to your computer and use it in GitHub Desktop.
object RedirectFilter extends Filter { | |
def apply(next: RequestHeader => Result)(request: RequestHeader): Result = { | |
getRedirectParams(request).flatMap { case (newRequest, body) => | |
route(newRequest).map { iteratee => | |
AsyncResult(Enumerator(body).run(iteratee)) | |
} | |
} getOrElse { | |
next(request) | |
} | |
} | |
private def getRedirectParams(request: RequestHeader): Option[(RequestHeader, Array[Byte])] = { | |
if (someCondition) { | |
Some(toPostRequest(request), "Some new body data".getBytes("UTF-8")) | |
} else { | |
None | |
} | |
} | |
private def toPostRequest(originalRequest: RequestHeader): RequestHeader = { | |
originalRequest.copy( | |
uri = "/some/new/uri", | |
path = "/some/new/uri", | |
method = "POST" | |
) | |
} | |
private def route(request: RequestHeader): Option[Iteratee[Array[Byte], Result]] = { | |
Play.global.onRouteRequest(request).collect { | |
case action: EssentialAction => Play.global.doFilter(action)(request) | |
} | |
} | |
} |
@brikis98 Yes I see, you are right, there is 2 pieces of logic (concerning the Action invocation) applied in the Netty handler directly. For now I don't see how you could solve that. The only way id to do it yourself.
To be sure that the requestHeader is properly tagged, I think you need something like:
Play.global.onRouteRequest(request).collect {
case action: EssentialAction => Play.global.doFilter(action)(request match {
case r: RequestTaggingHandler => r.tagRequest(request)
case _ => request
})
}
It would probably be better if we could extract this "Action invocation steps" outside of the Netty handler to avoid the repetition and to make it available for plugins and tests. It seems easy, but perhaps there is additional problems I don't see here. You should bring this discussion to the play-framework-dev Google group.
Ok, so you want to supply a new body? If you don't want to supply a new body, then the easiest way is to do it in onRouteRequest
. But if you want to supply a new body, you could do this in onRouteRequest too, but as a filter, you should use EssentialFilter
:
object RedirectFilter extends EssentialFilter {
def apply(next: EssentialAction) = new EssentialAction {
def apply(rh: RequestHeader) = {
getRedirectParams(rh).flatMap { case (newRequest, body) =>
route(newRequest).map { iteratee =>
// Ignore the actual body - or you could consume it and transform it somehow.
Iteratee.ignore[Array[Byte]].mapM { _ =>
// Feed in the new body to the new action
Enumerator(body) |>>> iteratee
}
}
} getOrElse {
next(request)
}
}
}
// Other methods go here, and like Guillaume pointed out, make sure you tag it
}
@brikis98 Yes I see, you are right, there is 2 pieces of logic (concerning the Action invocation) applied in the Netty handler directly. For now I don't see how you could solve that. The only way id to do it yourself.
To be sure that the requestHeader is properly tagged, I think you need something like:
It would probably be better if we could extract this "Action invocation steps" outside of the Netty handler to avoid the repetition and to make it available for plugins and tests. It seems easy, but perhaps there is additional problems I don't see here. You should bring this discussion to the play-framework-dev Google group.