+htp #19756: Add extractData and extractRequestEntity directives. (#20730)

* 19756: Add extractData and extractRequestEntity directives.

remove unnecessary import

* #19756: add documentation to extractDataBytes and extractRequestEntity directives
This commit is contained in:
kwyczesany 2016-06-07 21:02:38 +02:00 committed by Konrad Malawski
parent 735060da20
commit 7fdd5983a3
8 changed files with 147 additions and 1 deletions

View file

@ -795,5 +795,36 @@ class BasicDirectivesExamplesSpec extends RoutingSpec {
}
//#
}
"extractRequestEntity-example" in {
//#extractRequestEntity-example
val route =
extractRequestEntity { entity =>
complete(s"Request entity content-type is ${entity.contentType}")
}
// tests:
val httpEntity = HttpEntity(ContentTypes.`text/plain(UTF-8)`, "req")
Post("/abc", httpEntity) ~> route ~> check {
responseAs[String] shouldEqual s"Request entity content-type is text/plain; charset=UTF-8"
}
//#
}
"extractDataBytes-example" in {
//#extractDataBytes-example
val route =
extractDataBytes { data
val sum = data.runFold(0) { (acc, i) acc + i.utf8String.toInt }
onSuccess(sum) { s
complete(HttpResponse(entity = HttpEntity(s.toString)))
}
}
// tests:
val dataBytes = Source.fromIterator(() Iterator.range(1, 10).map(x ByteString(x.toString)))
Post("/abc", HttpEntity(ContentTypes.`text/plain(UTF-8)`, data = dataBytes)) ~> route ~> check {
responseAs[String] shouldEqual "45"
}
//#
}
}

View file

@ -47,6 +47,7 @@ Directive Description
via the ``Accept-Encoding`` header (from a user-defined set)
:ref:`-entity-` Extracts the request entity unmarshalled to a given type
:ref:`-extract-` Extracts a single value using a ``RequestContext ⇒ T`` function
:ref:`-extractDataBytes-` Extracts the entities data bytes as a stream ``Source[ByteString, Any]``
:ref:`-extractClientIP-` Extracts the client's IP from either the ``X-Forwarded-``,
``Remote-Address`` or ``X-Real-IP`` header
:ref:`-extractCredentials-` Extracts the potentially present ``HttpCredentials`` provided with the
@ -58,6 +59,7 @@ Directive Description
:ref:`-extractMethod-` Extracts the request method
:ref:`-extractRequest-` Extracts the current ``HttpRequest`` instance
:ref:`-extractRequestContext-` Extracts the ``RequestContext`` itself
:ref:`-extractRequestEntity-` Extracts the ``RequestEntity`` from the ``RequestContext``
:ref:`-extractScheme-` Extracts the URI scheme from the request
:ref:`-extractSettings-` Extracts the ``RoutingSettings`` from the ``RequestContext``
:ref:`-extractUnmatchedPath-` Extracts the yet unmatched path from the ``RequestContext``

View file

@ -0,0 +1,24 @@
.. _-extractDataBytes-:
extractDataBytes
================
Signature
---------
.. includecode2:: /../../akka-http/src/main/scala/akka/http/scaladsl/server/directives/BasicDirectives.scala
:snippet: extractDataBytes
Description
-----------
Extracts the entities data bytes as ``Source[ByteString, Any]`` from the :class:`RequestContext`.
The directive returns a stream containing the request data bytes.
Example
-------
.. includecode2:: ../../../../code/docs/http/scaladsl/server/directives/BasicDirectivesExamplesSpec.scala
:snippet: extractDataBytes-example

View file

@ -0,0 +1,25 @@
.. _-extractRequestEntity-:
extractRequestEntity
====================
Signature
---------
.. includecode2:: /../../akka-http/src/main/scala/akka/http/scaladsl/server/directives/BasicDirectives.scala
:snippet: extractRequestEntity
Description
-----------
Extracts the ``RequestEntity`` from the :class:`RequestContext`.
The directive returns a ``RequestEntity`` without unmarshalling the request. To extract domain entity,
:ref:`-entity-` should be used.
Example
-------
.. includecode2:: ../../../../code/docs/http/scaladsl/server/directives/BasicDirectivesExamplesSpec.scala
:snippet: extractRequestEntity-example

View file

@ -17,11 +17,13 @@ on two axes: a) provide a constant value or extract a value from the ``RequestCo
a single value or a tuple of values.
* :ref:`-extract-`
* :ref:`-extractDataBytes-`
* :ref:`-extractExecutionContext-`
* :ref:`-extractMaterializer-`
* :ref:`-extractLog-`
* :ref:`-extractRequest-`
* :ref:`-extractRequestContext-`
* :ref:`-extractRequestEntity-`
* :ref:`-extractSettings-`
* :ref:`-extractUnmatchedPath-`
* :ref:`-extractUri-`
@ -94,10 +96,12 @@ Alphabetically
cancelRejections
extract
extractExecutionContext
extractDataBytes
extractMaterializer
extractLog
extractRequest
extractRequestContext
extractRequestEntity
extractSettings
extractUnmatchedPath
extractUri

View file

@ -5,6 +5,10 @@
package akka.http.scaladsl.server
package directives
import akka.http.scaladsl.model._
import akka.stream.scaladsl.Source
import akka.util.ByteString
class BasicDirectivesSpec extends RoutingSpec {
"The `mapUnmatchedPath` directive" should {
@ -26,4 +30,27 @@ class BasicDirectivesSpec extends RoutingSpec {
} ~> check { responseAs[String] shouldEqual "GET" }
}
}
"The `extractDataBytes` directive" should {
"extract stream of ByteString from the RequestContext" in {
val dataBytes = Source.fromIterator(() Iterator.range(1, 10).map(x ByteString(x.toString)))
Post("/abc", HttpEntity(ContentTypes.`text/plain(UTF-8)`, data = dataBytes)) ~> {
extractDataBytes { data
val sum = data.runFold(0) { (acc, i) acc + i.utf8String.toInt }
onSuccess(sum) { s
complete(HttpResponse(entity = HttpEntity(s.toString)))
}
}
} ~> check { responseAs[String] shouldEqual "45" }
}
}
"The `extractRequestEntity` directive" should {
"extract entity from the RequestContext" in {
val httpEntity = HttpEntity(ContentTypes.`text/plain(UTF-8)`, "req")
Post("/abc", httpEntity) ~> {
extractRequestEntity { complete(_) }
} ~> check { responseEntity shouldEqual httpEntity }
}
}
}

View file

@ -10,6 +10,8 @@ import akka.http.impl.util.JavaMapping
import akka.http.javadsl.settings.ParserSettings
import akka.http.javadsl.settings.RoutingSettings
import akka.japi.Util
import akka.stream.javadsl.Source
import akka.util.ByteString
import scala.concurrent.ExecutionContextExecutor
import akka.http.impl.model.JavaUri
@ -184,7 +186,7 @@ abstract class BasicDirectives {
* Extracts the current http request entity.
*/
@CorrespondsTo("extract")
def extractEntity(inner: java.util.function.Function[RequestEntity, Route]): Route = RouteAdapter {
def extractEntity(inner: JFunction[RequestEntity, Route]): Route = RouteAdapter {
D.extractRequest { rq
inner.apply(rq.entity).delegate
}
@ -269,4 +271,16 @@ abstract class BasicDirectives {
D.extractRequestContext { ctx inner.apply(JavaMapping.toJava(ctx)(server.RoutingJavaMapping.RequestContext)).delegate }
}
/**
* Extracts the entities `dataBytes` [[akka.stream.javadsl.Source]] from the [[akka.http.javadsl.server.RequestContext]].
*/
def extractDataBytes(inner: JFunction[Source[ByteString, Any], Route]) = RouteAdapter {
D.extractRequest { ctx inner.apply(ctx.entity.dataBytes.asJava).delegate }
}
/**
* Extracts the [[akka.http.javadsl.model.RequestEntity]] from the [[akka.http.javadsl.server.RequestContext]].
*/
def extractRequestEntity(inner: JFunction[RequestEntity, Route]): Route = extractEntity(inner)
}

View file

@ -5,6 +5,9 @@
package akka.http.scaladsl.server
package directives
import akka.stream.scaladsl.Source
import akka.util.ByteString
import scala.concurrent.{ Future, ExecutionContextExecutor }
import scala.collection.immutable
import akka.event.LoggingAdapter
@ -284,6 +287,20 @@ trait BasicDirectives {
* @group basic
*/
def extractRequestContext: Directive1[RequestContext] = BasicDirectives._extractRequestContext
/**
* Extracts the [[akka.http.scaladsl.model.RequestEntity]] from the [[akka.http.scaladsl.server.RequestContext]].
*
* @group basic
*/
def extractRequestEntity: Directive1[RequestEntity] = BasicDirectives._extractRequestEntity
/**
* Extracts the entities `dataBytes` [[akka.stream.scaladsl.Source]] from the [[akka.http.scaladsl.server.RequestContext]].
*
* @group basic
*/
def extractDataBytes: Directive1[Source[ByteString, Any]] = BasicDirectives._extractDataBytes
}
object BasicDirectives extends BasicDirectives {
@ -296,4 +313,6 @@ object BasicDirectives extends BasicDirectives {
private val _extractSettings: Directive1[RoutingSettings] = extract(_.settings)
private val _extractParserSettings: Directive1[ParserSettings] = extract(_.parserSettings)
private val _extractRequestContext: Directive1[RequestContext] = extract(conforms)
private val _extractRequestEntity: Directive1[RequestEntity] = extract(_.request.entity)
private val _extractDataBytes: Directive1[Source[ByteString, Any]] = extract(_.request.entity.dataBytes)
}