=htc #17664 create Multipart.toEntity to simplify creation of multipart/formdata requests
This moves some functionality from marshallers in akka-http directly to akka-http-core.
This commit is contained in:
parent
b4272b77c2
commit
e9674d3ff0
3 changed files with 54 additions and 25 deletions
|
|
@ -5,6 +5,8 @@
|
|||
package akka.http.impl.engine.rendering
|
||||
|
||||
import java.nio.charset.Charset
|
||||
import akka.parboiled2.util.Base64
|
||||
|
||||
import scala.collection.immutable
|
||||
import akka.event.LoggingAdapter
|
||||
import akka.http.scaladsl.model._
|
||||
|
|
@ -16,6 +18,8 @@ import akka.stream.stage._
|
|||
import akka.util.ByteString
|
||||
import HttpEntity._
|
||||
|
||||
import scala.concurrent.forkjoin.ThreadLocalRandom
|
||||
|
||||
/**
|
||||
* INTERNAL API
|
||||
*/
|
||||
|
|
@ -110,4 +114,13 @@ private[http] object BodyPartRenderer {
|
|||
|
||||
case x ⇒ r ~~ x ~~ CrLf
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new random number of the given length and base64 encodes it (using a custom "safe" alphabet).
|
||||
*/
|
||||
def randomBoundary(length: Int = 18, random: java.util.Random = ThreadLocalRandom.current()): String = {
|
||||
val array = new Array[Byte](length)
|
||||
random.nextBytes(array)
|
||||
Base64.custom.encodeToString(array, false)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,15 +4,18 @@
|
|||
|
||||
package akka.http.scaladsl.model
|
||||
|
||||
import akka.event.{ NoLogging, LoggingAdapter }
|
||||
|
||||
import scala.collection.immutable.VectorBuilder
|
||||
import scala.concurrent.duration.FiniteDuration
|
||||
import scala.concurrent.{ Future, ExecutionContext }
|
||||
import scala.collection.immutable
|
||||
import scala.util.{ Failure, Success, Try }
|
||||
import akka.stream.FlowMaterializer
|
||||
import akka.stream.scaladsl.Source
|
||||
import akka.stream.scaladsl.{ FlattenStrategy, Source }
|
||||
import akka.http.scaladsl.util.FastFuture
|
||||
import akka.http.scaladsl.model.headers._
|
||||
import akka.http.impl.engine.rendering.BodyPartRenderer
|
||||
import FastFuture._
|
||||
|
||||
trait Multipart {
|
||||
|
|
@ -25,12 +28,29 @@ trait Multipart {
|
|||
* The Future is failed with an TimeoutException if one part isn't read completely after the given timeout.
|
||||
*/
|
||||
def toStrict(timeout: FiniteDuration)(implicit ec: ExecutionContext, fm: FlowMaterializer): Future[Multipart.Strict]
|
||||
|
||||
/**
|
||||
* Creates an entity from this multipart object.
|
||||
*/
|
||||
def toEntity(charset: HttpCharset = HttpCharsets.`UTF-8`,
|
||||
boundary: String = BodyPartRenderer.randomBoundary())(implicit log: LoggingAdapter = NoLogging): MessageEntity = {
|
||||
val chunks =
|
||||
parts
|
||||
.transform(() ⇒ BodyPartRenderer.streamed(boundary, charset.nioCharset, partHeadersSizeHint = 128, log))
|
||||
.flatten(FlattenStrategy.concat)
|
||||
HttpEntity.Chunked(mediaType withBoundary boundary, chunks)
|
||||
}
|
||||
}
|
||||
|
||||
object Multipart {
|
||||
|
||||
trait Strict extends Multipart {
|
||||
def strictParts: immutable.Seq[BodyPart.Strict]
|
||||
|
||||
override def toEntity(charset: HttpCharset, boundary: String)(implicit log: LoggingAdapter = NoLogging): HttpEntity.Strict = {
|
||||
val data = BodyPartRenderer.strict(strictParts, boundary, charset.nioCharset, partHeadersSizeHint = 128, log)
|
||||
HttpEntity(mediaType withBoundary boundary, data)
|
||||
}
|
||||
}
|
||||
|
||||
trait BodyPart {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue