Skip to content

Commit

Permalink
Formatting + headers
Browse files Browse the repository at this point in the history
  • Loading branch information
mkurz committed Aug 17, 2023
1 parent 831920a commit cc8308f
Show file tree
Hide file tree
Showing 10 changed files with 83 additions and 75 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) Lightbend Inc. <https://www.lightbend.com>
* Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com>
*/

package play.it.http.parsingdeferred;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
/*
* Copyright (C) Lightbend Inc. <https://www.lightbend.com>
* Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com>
*/

package play.it.http.parsingdeferred;

import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Result;
import play.mvc.With;
import static play.it.http.parsingdeferred.DeferredBodyParsingSpec.buildActionCompositionMessage;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.CompletionStage;

import static play.it.http.parsingdeferred.DeferredBodyParsingSpec.buildActionCompositionMessage;
import play.mvc.Action;
import play.mvc.Http;
import play.mvc.Result;
import play.mvc.With;

@With(SimpleActionAnnotationAction.class)
@Target({ElementType.TYPE, ElementType.METHOD})
Expand Down
Original file line number Diff line number Diff line change
@@ -1,50 +1,50 @@
/*
* Copyright (C) Lightbend Inc. <https://www.lightbend.com>
* Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com>
*/

package play.it.http.parsingdeferred

import java.util.concurrent.CompletableFuture

import scala.concurrent.ExecutionContext
import scala.concurrent.Future

import akka.actor.ActorSystem
import akka.stream.Materializer
import akka.stream.scaladsl.Sink
import akka.stream.javadsl.{ Sink => JSink }
import akka.stream.scaladsl.Sink
import akka.stream.Materializer
import akka.util.ByteString
import com.typesafe.config.ConfigFactory
import org.specs2.specification.core.Fragment
import org.specs2.specification.AfterAll
import org.specs2.specification.AfterEach
import org.specs2.specification.BeforeAll
import play.api.Application
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.libs.streams.Accumulator
import play.api.libs.ws.DefaultBodyWritables.writeableOf_String
import play.api.libs.ws.DefaultBodyReadables.readableAsString
import play.api.libs.ws.DefaultBodyWritables.writeableOf_String
import play.api.libs.ws.WSResponse
import play.api.mvc.Handler.Stage
import play.api.mvc._
import play.api.mvc.request.RequestAttrKey.DeferredBodyParserInvoker
import play.api.mvc.Handler.Stage
import play.api.routing.HandlerDef
import play.api.routing.Router
import play.api.test.Helpers
import play.api.test.PlaySpecification
import play.api.test.WsTestClient
import play.api.mvc.request.RequestAttrKey.DeferredBodyParserInvoker
import play.api.Application
import play.it.http.JAction
import play.it.http.MockController
import play.it.AkkaHttpIntegrationSpecification
import play.it.NettyIntegrationSpecification
import play.it.ServerIntegrationSpecification
import play.libs.F
import play.libs.streams.{ Accumulator => JAccumulator }
import play.mvc.Http.{ Request => JRequest }
import play.mvc.Http
import play.mvc.Results
import play.libs.F
import play.mvc.{ BodyParser => JBodyParser }
import play.mvc.{ Result => JResult }

import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import play.mvc.Http
import play.mvc.Http.{ Request => JRequest }
import play.mvc.Results

class AkkaHttpServerDeferredBodyParsingSpec extends DeferredBodyParsingSpec with AkkaHttpIntegrationSpecification {
override def serverBackend(): String = "akka-http"
Expand Down Expand Up @@ -83,11 +83,11 @@ object DeferredBodyParsingSpec {

def buildParserDebugMessage(request: RequestHeader, parsedBody: String) =
s"Body parsed: $parsedBody, request attribute set: ${request.attrs.contains(Attrs.REQUEST_FLOW.asScala())}, internal request attribute set: ${request.attrs
.contains(DeferredBodyParserInvoker)}"
.contains(DeferredBodyParserInvoker)}"

def buildActionCompositionMessage(request: Request[_]) =
s"Action composition, body was parsed already: ${(request.body != null)}, internal request attribute set: ${request.attrs
.contains(DeferredBodyParserInvoker)}"
.contains(DeferredBodyParserInvoker)}"
}

trait DeferredBodyParsingSpec
Expand Down
4 changes: 2 additions & 2 deletions core/play/src/main/scala/play/api/mvc/Action.scala
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,10 @@ object BodyParser {
false
)
})
.getOrElse({
.getOrElse {
logger.trace("Not parsing body, was parsed before already for request: " + request)
next(request)
})
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

package play.api.mvc.request

import scala.concurrent.Future

import akka.util.ByteString
import play.api.libs.streams.Accumulator
import play.api.libs.typedmap.TypedKey
Expand All @@ -12,8 +14,6 @@ import play.api.mvc.Flash
import play.api.mvc.Result
import play.api.mvc.Session

import scala.concurrent.Future

/**
* Keys to request attributes.
*/
Expand Down
15 changes: 8 additions & 7 deletions core/play/src/main/scala/play/core/j/JavaAction.scala
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,14 @@ abstract class JavaAction(val handlerComponents: JavaHandlerComponents)
override def call(request: JRequest): CompletionStage[JResult] =
// It's totally OK to call parseBody(...) even when body parsing was not deferred because it won't do anything
// if body was parsed already and just passes through
BodyParser
.parseBody(
parser,
request.asScala(),
(r: Request[_]) => invocation(r.asJava).asScala.map(_.asScala())
)(executionContext)
.map(_.asJava).asJava
BodyParser
.parseBody(
parser,
request.asScala(),
(r: Request[_]) => invocation(r.asJava).asScala.map(_.asScala())
)(executionContext)
.map(_.asJava)
.asJava
}

val baseAction = handlerComponents.actionCreator.createAction(javaRequest, annotations.method)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,31 +456,31 @@ class AkkaHttpServer(context: AkkaHttpServer.Context) extends Server {
// Captures the source and the (implicit) materializer.
// Meaning no matter if parsing is deferred, it always uses the same materializer.
def invokeAction(futureAcc: Future[Accumulator[ByteString, Result]], deferBodyParsing: Boolean): Future[Result] =
// here we use FastFuture so the flatMap shouldn't actually need the executionContext
futureAcc.fast
.flatMap { actionAccumulator =>
{
if (deferBodyParsing) {
actionAccumulator.run() // don't parse anything
} else {
source match {
case Left(bytes) if bytes.isEmpty => actionAccumulator.run()
case Left(bytes) => actionAccumulator.run(bytes)
case Right(s) => actionAccumulator.run(s)
}
// here we use FastFuture so the flatMap shouldn't actually need the executionContext
futureAcc.fast
.flatMap { actionAccumulator =>
{
if (deferBodyParsing) {
actionAccumulator.run() // don't parse anything
} else {
source match {
case Left(bytes) if bytes.isEmpty => actionAccumulator.run()
case Left(bytes) => actionAccumulator.run(bytes)
case Right(s) => actionAccumulator.run(s)
}
}
}(mat.executionContext)
.recoverWith {
case _: EntityStreamSizeException =>
errorHandler.onClientError(
taggedRequestHeader.addAttr(HttpErrorHandler.Attrs.HttpErrorInfo, HttpErrorInfo("server-backend")),
Status.REQUEST_ENTITY_TOO_LARGE,
"Request Entity Too Large"
)
case e: Throwable =>
errorHandler.onServerError(taggedRequestHeader, e)
}(mat.executionContext)
}
}(mat.executionContext)
.recoverWith {
case _: EntityStreamSizeException =>
errorHandler.onClientError(
taggedRequestHeader.addAttr(HttpErrorHandler.Attrs.HttpErrorInfo, HttpErrorInfo("server-backend")),
Status.REQUEST_ENTITY_TOO_LARGE,
"Request Entity Too Large"
)
case e: Throwable =>
errorHandler.onServerError(taggedRequestHeader, e)
}(mat.executionContext)

val deferBodyParsing = deferredBodyParsingAllowed &&
Server.routeModifierDefersBodyParsing(serverConfig.underlying.getBoolean("deferBodyParsing"), taggedRequestHeader)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,15 @@ class NettyServer(
* Create a new PlayRequestHandler.
*/
protected[this] def newRequestHandler(): ChannelInboundHandler =
new PlayRequestHandler(this, serverHeader, maxContentLength, wsBufferLimit, wsKeepAliveMode, wsKeepAliveMaxIdle, deferBodyParsing)
new PlayRequestHandler(
this,
serverHeader,
maxContentLength,
wsBufferLimit,
wsKeepAliveMode,
wsKeepAliveMaxIdle,
deferBodyParsing
)

/**
* Create a sink for the incoming connection channels.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,23 +306,23 @@ private[play] class PlayRequestHandler(
// Captures the Netty HttpRequest and the (implicit) materializer.
// Meaning no matter if parsing is deferred, it always uses the same materializer.
def invokeAction(actionFuture: Future[Accumulator[ByteString, Result]], deferBodyParsing: Boolean): Future[Result] =
actionFuture
.flatMap { acc =>
if (deferBodyParsing) {
acc.run() // don't parse anything
} else {
val body = modelConversion(tryApp).convertRequestBody(request)
body match {
case None => acc.run()
case Some(source) => acc.run(source)
}
actionFuture
.flatMap { acc =>
if (deferBodyParsing) {
acc.run() // don't parse anything
} else {
val body = modelConversion(tryApp).convertRequestBody(request)
body match {
case None => acc.run()
case Some(source) => acc.run(source)
}
}
.recoverWith {
case error =>
logger.error("Cannot invoke the action", error)
errorHandler(tryApp).onServerError(requestHeader, error)
}
}
.recoverWith {
case error =>
logger.error("Cannot invoke the action", error)
errorHandler(tryApp).onServerError(requestHeader, error)
}

val deferBodyParsing = deferredBodyParsingAllowed &&
Server.routeModifierDefersBodyParsing(deferBodyParsingGlobal, requestHeader)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) Lightbend Inc. <https://www.lightbend.com>
* Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com>
*/

package play.core.server
Expand Down

0 comments on commit cc8308f

Please sign in to comment.