@Singleton
class ResponseExpander @Inject() (
implicit ec: ExecutionContext,
implicit val mat: Materializer) extends EssentialFilter {
def apply(nextFilter: EssentialAction) = new EssentialAction {
def apply(requestHeader: RequestHeader) = {
def pad(b: Byte): ByteString = {
b.toChar match {
case c if c.isLetter => ByteString(c, c)
case _ => ByteString(b)
}
}
val accumulator: Accumulator[ByteString, Result] = nextFilter(requestHeader)
accumulator.mapFuture(res => {
res.body.consumeData.map(bytes => bytes.flatMap(pad))
.map(bytes => {
val entity = HttpEntity.Strict(bytes, requestHeader.headers.get(CONTENT_TYPE))
Result(res.header, entity)
})
})
}
}
}
--
You received this message because you are subscribed to a topic in the Google Groups "Play Framework" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/play-framework/oxajoitkX68/unsubscribe.
To unsubscribe from this group and all its topics, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/3ae11b10-9742-4293-a351-f23adbb527fc%40googlegroups.com.
To unsubscribe from this group and all its topics, send an email to play-framewor...@googlegroups.com.
package filters
import javax.inject.{Inject, Singleton}
import akka.stream.scaladsl.Flow
import akka.stream.stage.{GraphStage, GraphStageLogic, InHandler, OutHandler}
import akka.stream.{Attributes, FlowShape, Materializer}
import akka.util.ByteString
import play.api.libs.streams.Accumulator
import play.api.mvc.{EssentialAction, EssentialFilter, RequestHeader, Result}
import scala.collection.mutable
import scala.concurrent.ExecutionContext
@Singleton
class RequestExpander @Inject() (
implicit ec: ExecutionContext,
implicit val mat: Materializer) extends EssentialFilter {
def apply(nextFilter: EssentialAction) = new EssentialAction {
def apply(requestHeader: RequestHeader) = {
def pad(b: Byte): ByteString = {
b.toChar match {
case c if c.isLetter => ByteString(c, c)
case _ => ByteString(b)
}
}
val accumulator: Accumulator[ByteString, Result] = nextFilter(requestHeader)
val graph = new FullBodyFilterGraphStage(bytes => bytes.flatMap(pad))
accumulator.through(Flow.fromGraph(graph))
}
}
/**
* Internal helper class, based on
* http://doc.akka.io/docs/akka/2.4/scala/stream/stream-cookbook.html#Calculating_the_digest_of_a_ByteString_stream
*
* @param filter Body filtering function
*/
class FullBodyFilterGraphStage(filter: ByteString => ByteString) extends GraphStage[FlowShape[ByteString, ByteString]] {
val flow = Flow.fromFunction[ByteString, ByteString](identity)
override val shape = flow.shape
val in = shape.in
val out = shape.out
override def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) {
val buffer = mutable.ArrayBuilder.make[Byte]()
setHandler(out, new OutHandler {
override def onPull(): Unit = {
pull(in)
}
})
setHandler(in, new InHandler {
override def onPush(): Unit = {
val chunk = grab(in)
buffer ++= chunk.toArray
pull(in)
}
override def onUpstreamFinish(): Unit = {
val bytes = buffer.result
emit(out, filter(ByteString(buffer.result)))
completeStage()
}
})
}
}
}
package controllers
import com.google.inject.Inject
import com.livongo.common.util.Contexts.playContext
import play.api.mvc._
import scala.concurrent.Future
class AppController @Inject() extends Controller {
def filterDemo = Action.async { implicit request =>
Future {
request.body.asText match {
case Some(body) => Ok(s"Got request body:\n$body")
case None => NoContent
}
}
}
}