!htc #16803 introduce proper model for type of media-type encoding specs
This commit is contained in:
parent
37aa2cb886
commit
5074aebfeb
10 changed files with 109 additions and 69 deletions
|
|
@ -185,10 +185,10 @@ public abstract class MediaTypes {
|
|||
String mainType,
|
||||
String subType,
|
||||
boolean compressible,
|
||||
boolean binary,
|
||||
akka.http.model.MediaType.Encoding encoding,
|
||||
Iterable<String> fileExtensions,
|
||||
Map<String, String> params) {
|
||||
return akka.http.model.MediaType.custom(mainType, subType, compressible, binary, Util.<String, String>convertIterable(fileExtensions), Util.convertMapToScala(params), false);
|
||||
return akka.http.model.MediaType.custom(mainType, subType, encoding, compressible, Util.<String, String>convertIterable(fileExtensions), Util.convertMapToScala(params), false);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -37,19 +37,23 @@ object ContentTypeRange {
|
|||
}
|
||||
}
|
||||
|
||||
final case class ContentType(mediaType: MediaType, definedCharset: Option[HttpCharset]) extends japi.ContentType with ValueRenderable {
|
||||
abstract case class ContentType private (mediaType: MediaType, definedCharset: Option[HttpCharset]) extends japi.ContentType with ValueRenderable {
|
||||
def render[R <: Rendering](r: R): r.type = definedCharset match {
|
||||
case Some(cs) ⇒ r ~~ mediaType ~~ ContentType.`; charset=` ~~ cs
|
||||
case _ ⇒ r ~~ mediaType
|
||||
}
|
||||
def charset: HttpCharset = definedCharset getOrElse HttpCharsets.`UTF-8`
|
||||
def charset: HttpCharset = definedCharset orElse mediaType.encoding.charset getOrElse HttpCharsets.`UTF-8`
|
||||
|
||||
def hasOpenCharset: Boolean = definedCharset.isEmpty && mediaType.encoding == MediaType.Encoding.Open
|
||||
|
||||
def withMediaType(mediaType: MediaType) =
|
||||
if (mediaType != this.mediaType) copy(mediaType = mediaType) else this
|
||||
if (mediaType != this.mediaType) ContentType(mediaType, definedCharset) else this
|
||||
def withCharset(charset: HttpCharset) =
|
||||
if (definedCharset.isEmpty || charset != definedCharset.get) copy(definedCharset = Some(charset)) else this
|
||||
if (definedCharset.isEmpty || charset != definedCharset.get) ContentType(mediaType, charset) else this
|
||||
def withoutDefinedCharset =
|
||||
if (definedCharset.isDefined) copy(definedCharset = None) else this
|
||||
if (definedCharset.isDefined) ContentType(mediaType, None) else this
|
||||
def withDefaultCharset(charset: HttpCharset) =
|
||||
if (mediaType.encoding == MediaType.Encoding.Open && definedCharset.isEmpty) ContentType(mediaType, charset) else this
|
||||
|
||||
/** Java API */
|
||||
def getDefinedCharset: JOption[japi.HttpCharset] = definedCharset.asJava
|
||||
|
|
@ -58,13 +62,27 @@ final case class ContentType(mediaType: MediaType, definedCharset: Option[HttpCh
|
|||
object ContentType {
|
||||
private[http] case object `; charset=` extends SingletonValueRenderable
|
||||
|
||||
def apply(mediaType: MediaType, charset: HttpCharset): ContentType = apply(mediaType, Some(charset))
|
||||
implicit def apply(mediaType: MediaType): ContentType = apply(mediaType, None)
|
||||
|
||||
def apply(mediaType: MediaType, charset: HttpCharset): ContentType = apply(mediaType, Some(charset))
|
||||
|
||||
def apply(mediaType: MediaType, charset: Option[HttpCharset]): ContentType = {
|
||||
val definedCharset =
|
||||
charset match {
|
||||
case None ⇒ None
|
||||
case Some(cs) ⇒ mediaType.encoding match {
|
||||
case MediaType.Encoding.Open ⇒ charset
|
||||
case MediaType.Encoding.Fixed(`cs`) ⇒ None
|
||||
case x ⇒ throw new IllegalArgumentException(
|
||||
s"MediaType $mediaType has a $x encoding and doesn't allow a custom `charset` $cs")
|
||||
}
|
||||
}
|
||||
new ContentType(mediaType, definedCharset) {}
|
||||
}
|
||||
}
|
||||
|
||||
object ContentTypes {
|
||||
// RFC4627 defines JSON to always be UTF encoded, we always render JSON to UTF-8
|
||||
val `application/json` = ContentType(MediaTypes.`application/json`, HttpCharsets.`UTF-8`)
|
||||
val `application/json` = ContentType(MediaTypes.`application/json`)
|
||||
val `text/plain` = ContentType(MediaTypes.`text/plain`)
|
||||
val `text/plain(UTF-8)` = ContentType(MediaTypes.`text/plain`, HttpCharsets.`UTF-8`)
|
||||
val `application/octet-stream` = ContentType(MediaTypes.`application/octet-stream`)
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ object MediaRange {
|
|||
override def isMultipart = mainType == "multipart"
|
||||
override def isText = mainType == "text"
|
||||
override def isVideo = mainType == "video"
|
||||
def specimen = MediaType.custom(mainType, "custom")
|
||||
def specimen = MediaType.custom(mainType, "custom", MediaType.Encoding.Binary)
|
||||
}
|
||||
|
||||
def custom(mainType: String, params: Map[String, String] = Map.empty, qValue: Float = 1.0f): MediaRange = {
|
||||
|
|
@ -165,7 +165,7 @@ object MediaRanges extends ObjectRegistry[String, MediaRange] {
|
|||
sealed abstract case class MediaType private[http] (value: String)(val mainType: String,
|
||||
val subType: String,
|
||||
val compressible: Boolean,
|
||||
val binary: Boolean,
|
||||
val encoding: MediaType.Encoding,
|
||||
val fileExtensions: immutable.Seq[String],
|
||||
val params: Map[String, String])
|
||||
extends japi.MediaType with LazyValueBytesRenderable with WithQValue[MediaRange] {
|
||||
|
|
@ -191,7 +191,7 @@ sealed abstract case class MediaType private[http] (value: String)(val mainType:
|
|||
}
|
||||
|
||||
class MultipartMediaType private[http] (_value: String, _subType: String, _params: Map[String, String])
|
||||
extends MediaType(_value)("multipart", _subType, compressible = true, binary = true, Nil, _params) {
|
||||
extends MediaType(_value)("multipart", _subType, compressible = true, encoding = MediaType.Encoding.Open, Nil, _params) {
|
||||
override def isMultipart = true
|
||||
def withBoundary(boundary: String): MultipartMediaType = withParams {
|
||||
if (boundary.isEmpty) params - "boundary" else params.updated("boundary", boundary)
|
||||
|
|
@ -200,28 +200,47 @@ class MultipartMediaType private[http] (_value: String, _subType: String, _param
|
|||
}
|
||||
|
||||
sealed abstract class NonMultipartMediaType private[http] (_value: String, _mainType: String, _subType: String,
|
||||
_compressible: Boolean, _binary: Boolean,
|
||||
_compressible: Boolean, _encoding: MediaType.Encoding,
|
||||
_fileExtensions: immutable.Seq[String],
|
||||
_params: Map[String, String])
|
||||
extends MediaType(_value)(_mainType, _subType, _compressible, _binary, _fileExtensions, _params) {
|
||||
private[http] def this(mainType: String, subType: String, compressible: Boolean, binary: Boolean, fileExtensions: immutable.Seq[String]) =
|
||||
this(mainType + '/' + subType, mainType, subType, compressible, binary, fileExtensions, Map.empty)
|
||||
extends MediaType(_value)(_mainType, _subType, _compressible, _encoding, _fileExtensions, _params) {
|
||||
private[http] def this(mainType: String, subType: String, compressible: Boolean, encoding: MediaType.Encoding,
|
||||
fileExtensions: immutable.Seq[String]) =
|
||||
this(mainType + '/' + subType, mainType, subType, compressible, encoding, fileExtensions, Map.empty)
|
||||
def withParams(params: Map[String, String]) =
|
||||
MediaType.custom(mainType, subType, compressible, binary, fileExtensions, params)
|
||||
MediaType.custom(mainType, subType, encoding, compressible, fileExtensions, params)
|
||||
}
|
||||
|
||||
object MediaType {
|
||||
sealed abstract class Encoding(val charset: Option[HttpCharset])
|
||||
object Encoding {
|
||||
/**
|
||||
* Indicates that the media type is non-textual and a character encoding therefore has no meaning.
|
||||
*/
|
||||
case object Binary extends Encoding(None)
|
||||
|
||||
/**
|
||||
* Indicates that the media-type allow for flexible character encoding through a `charset` parameter.
|
||||
*/
|
||||
case object Open extends Encoding(None)
|
||||
|
||||
/**
|
||||
* Indicates that a media-type is textual and mandates a clearly defined character encoding.
|
||||
*/
|
||||
final case class Fixed(cs: HttpCharset) extends Encoding(Some(cs))
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a custom media type.
|
||||
*/
|
||||
def custom(mainType: String, subType: String, compressible: Boolean = false, binary: Boolean = false,
|
||||
fileExtensions: immutable.Seq[String] = Nil, params: Map[String, String] = Map.empty,
|
||||
allowArbitrarySubtypes: Boolean = false): MediaType = {
|
||||
def custom(mainType: String, subType: String, encoding: MediaType.Encoding,
|
||||
compressible: Boolean = false, fileExtensions: immutable.Seq[String] = Nil,
|
||||
params: Map[String, String] = Map.empty, allowArbitrarySubtypes: Boolean = false): MediaType = {
|
||||
require(mainType != "multipart", "Cannot create a MultipartMediaType here, use `multipart.apply` instead!")
|
||||
require(allowArbitrarySubtypes || subType != "*", "Cannot create a MediaRange here, use `MediaRange.custom` instead!")
|
||||
val r = new StringRendering ~~ mainType ~~ '/' ~~ subType
|
||||
if (params.nonEmpty) params foreach { case (k, v) ⇒ r ~~ ';' ~~ ' ' ~~ k ~~ '=' ~~# v }
|
||||
new NonMultipartMediaType(r.get, mainType, subType, compressible, binary, fileExtensions, params) {
|
||||
new NonMultipartMediaType(r.get, mainType, subType, compressible, encoding, fileExtensions, params) {
|
||||
override def isApplication = mainType == "application"
|
||||
override def isAudio = mainType == "audio"
|
||||
override def isImage = mainType == "image"
|
||||
|
|
@ -231,14 +250,16 @@ object MediaType {
|
|||
}
|
||||
}
|
||||
|
||||
def custom(value: String): MediaType = {
|
||||
def custom(value: String, encoding: MediaType.Encoding): MediaType = {
|
||||
val parts = value.split('/')
|
||||
if (parts.length != 2) throw new IllegalArgumentException(value + " is not a valid media-type")
|
||||
custom(parts(0), parts(1))
|
||||
custom(parts(0), parts(1), encoding)
|
||||
}
|
||||
}
|
||||
|
||||
object MediaTypes extends ObjectRegistry[(String, String), MediaType] {
|
||||
import MediaType.Encoding
|
||||
|
||||
private[this] var extensionMap = Map.empty[String, MediaType]
|
||||
|
||||
private def register(mediaType: MediaType): MediaType = {
|
||||
|
|
@ -253,33 +274,34 @@ object MediaTypes extends ObjectRegistry[(String, String), MediaType] {
|
|||
|
||||
def forExtension(ext: String): Option[MediaType] = extensionMap.get(ext.toRootLowerCase)
|
||||
|
||||
private def app(subType: String, compressible: Boolean, binary: Boolean, fileExtensions: String*) = register {
|
||||
new NonMultipartMediaType("application", subType, compressible, binary, immutable.Seq(fileExtensions: _*)) {
|
||||
private def app(subType: String, compressible: Boolean, encoding: Encoding, fileExtensions: String*) = register {
|
||||
new NonMultipartMediaType("application", subType, compressible, encoding, immutable.Seq(fileExtensions: _*)) {
|
||||
override def isApplication = true
|
||||
}
|
||||
}
|
||||
private def aud(subType: String, compressible: Boolean, fileExtensions: String*) = register {
|
||||
new NonMultipartMediaType("audio", subType, compressible, binary = true, immutable.Seq(fileExtensions: _*)) {
|
||||
new NonMultipartMediaType("audio", subType, compressible, encoding = Encoding.Binary, immutable.Seq(fileExtensions: _*)) {
|
||||
override def isAudio = true
|
||||
}
|
||||
}
|
||||
private def img(subType: String, compressible: Boolean, binary: Boolean, fileExtensions: String*) = register {
|
||||
new NonMultipartMediaType("image", subType, compressible, binary, immutable.Seq(fileExtensions: _*)) {
|
||||
private def img(subType: String, compressible: Boolean, encoding: Encoding, fileExtensions: String*) = register {
|
||||
new NonMultipartMediaType("image", subType, compressible, encoding, immutable.Seq(fileExtensions: _*)) {
|
||||
override def isImage = true
|
||||
}
|
||||
}
|
||||
private def msg(subType: String, fileExtensions: String*) = register {
|
||||
new NonMultipartMediaType("message", subType, compressible = true, binary = false, immutable.Seq(fileExtensions: _*)) {
|
||||
new NonMultipartMediaType("message", subType, compressible = true, encoding = Encoding.Binary,
|
||||
immutable.Seq(fileExtensions: _*)) {
|
||||
override def isMessage = true
|
||||
}
|
||||
}
|
||||
private def txt(subType: String, fileExtensions: String*) = register {
|
||||
new NonMultipartMediaType("text", subType, compressible = true, binary = false, immutable.Seq(fileExtensions: _*)) {
|
||||
new NonMultipartMediaType("text", subType, compressible = true, encoding = Encoding.Open, immutable.Seq(fileExtensions: _*)) {
|
||||
override def isText = true
|
||||
}
|
||||
}
|
||||
private def vid(subType: String, fileExtensions: String*) = register {
|
||||
new NonMultipartMediaType("video", subType, compressible = false, binary = true, immutable.Seq(fileExtensions: _*)) {
|
||||
new NonMultipartMediaType("video", subType, compressible = false, encoding = Encoding.Binary, immutable.Seq(fileExtensions: _*)) {
|
||||
override def isVideo = true
|
||||
}
|
||||
}
|
||||
|
|
@ -288,21 +310,21 @@ object MediaTypes extends ObjectRegistry[(String, String), MediaType] {
|
|||
// format: OFF
|
||||
private final val compressible = true // compile-time constant
|
||||
private final val uncompressible = false // compile-time constant
|
||||
private final val binary = true // compile-time constant
|
||||
private final val notBinary = false // compile-time constant
|
||||
private def binary = Encoding.Binary
|
||||
private def openEncoding = Encoding.Open
|
||||
|
||||
// dummy value currently only used by ContentType.NoContentType
|
||||
private[http] val NoMediaType = new NonMultipartMediaType("none", "none", false, false, immutable.Seq.empty) {}
|
||||
private[http] val NoMediaType = new NonMultipartMediaType("none", "none", false, Encoding.Binary, immutable.Seq.empty) {}
|
||||
|
||||
val `application/atom+xml` = app("atom+xml", compressible, notBinary, "atom")
|
||||
val `application/atom+xml` = app("atom+xml", compressible, openEncoding, "atom")
|
||||
val `application/base64` = app("base64", compressible, binary, "mm", "mme")
|
||||
val `application/excel` = app("excel", uncompressible, binary, "xl", "xla", "xlb", "xlc", "xld", "xlk", "xll", "xlm", "xls", "xlt", "xlv", "xlw")
|
||||
val `application/font-woff` = app("font-woff", uncompressible, binary, "woff")
|
||||
val `application/gnutar` = app("gnutar", uncompressible, binary, "tgz")
|
||||
val `application/java-archive` = app("java-archive", uncompressible, binary, "jar", "war", "ear")
|
||||
val `application/javascript` = app("javascript", compressible, notBinary, "js")
|
||||
val `application/json` = app("json", compressible, binary, "json") // we treat JSON as binary, since its encoding is not variable but defined by RFC4627
|
||||
val `application/json-patch+json` = app("json-patch+json", compressible, binary) // we treat JSON as binary, since its encoding is not variable but defined by RFC4627
|
||||
val `application/javascript` = app("javascript", compressible, openEncoding, "js")
|
||||
val `application/json` = app("json", compressible, Encoding.Fixed(HttpCharsets.`UTF-8`), "json")
|
||||
val `application/json-patch+json` = app("json-patch+json", compressible, Encoding.Fixed(HttpCharsets.`UTF-8`))
|
||||
val `application/lha` = app("lha", uncompressible, binary, "lha")
|
||||
val `application/lzx` = app("lzx", uncompressible, binary, "lzx")
|
||||
val `application/mspowerpoint` = app("mspowerpoint", uncompressible, binary, "pot", "pps", "ppt", "ppz")
|
||||
|
|
@ -310,10 +332,10 @@ object MediaTypes extends ObjectRegistry[(String, String), MediaType] {
|
|||
val `application/octet-stream` = app("octet-stream", uncompressible, binary, "a", "bin", "class", "dump", "exe", "lhx", "lzh", "o", "psd", "saveme", "zoo")
|
||||
val `application/pdf` = app("pdf", uncompressible, binary, "pdf")
|
||||
val `application/postscript` = app("postscript", compressible, binary, "ai", "eps", "ps")
|
||||
val `application/rss+xml` = app("rss+xml", compressible, notBinary, "rss")
|
||||
val `application/soap+xml` = app("soap+xml", compressible, notBinary)
|
||||
val `application/vnd.api+json` = app("vnd.api+json", compressible, binary) // we treat JSON as binary, since its encoding is not variable but defined by RFC4627
|
||||
val `application/vnd.google-earth.kml+xml` = app("vnd.google-earth.kml+xml", compressible, notBinary, "kml")
|
||||
val `application/rss+xml` = app("rss+xml", compressible, openEncoding, "rss")
|
||||
val `application/soap+xml` = app("soap+xml", compressible, openEncoding)
|
||||
val `application/vnd.api+json` = app("vnd.api+json", compressible, Encoding.Fixed(HttpCharsets.`UTF-8`))
|
||||
val `application/vnd.google-earth.kml+xml` = app("vnd.google-earth.kml+xml", compressible, openEncoding, "kml")
|
||||
val `application/vnd.google-earth.kmz` = app("vnd.google-earth.kmz", uncompressible, binary, "kmz")
|
||||
val `application/vnd.ms-fontobject` = app("vnd.ms-fontobject", compressible, binary, "eot")
|
||||
val `application/vnd.oasis.opendocument.chart` = app("vnd.oasis.opendocument.chart", compressible, binary, "odc")
|
||||
|
|
@ -356,13 +378,13 @@ object MediaTypes extends ObjectRegistry[(String, String), MediaType] {
|
|||
val `application/x-tar` = app("x-tar", compressible, binary, "tar")
|
||||
val `application/x-tex` = app("x-tex", compressible, binary, "tex")
|
||||
val `application/x-texinfo` = app("x-texinfo", compressible, binary, "texi", "texinfo")
|
||||
val `application/x-vrml` = app("x-vrml", compressible, notBinary, "vrml")
|
||||
val `application/x-www-form-urlencoded` = app("x-www-form-urlencoded", compressible, notBinary)
|
||||
val `application/x-vrml` = app("x-vrml", compressible, openEncoding, "vrml")
|
||||
val `application/x-www-form-urlencoded` = app("x-www-form-urlencoded", compressible, openEncoding)
|
||||
val `application/x-x509-ca-cert` = app("x-x509-ca-cert", compressible, binary, "der")
|
||||
val `application/x-xpinstall` = app("x-xpinstall", uncompressible, binary, "xpi")
|
||||
val `application/xhtml+xml` = app("xhtml+xml", compressible, notBinary)
|
||||
val `application/xml-dtd` = app("xml-dtd", compressible, notBinary)
|
||||
val `application/xml` = app("xml", compressible, notBinary)
|
||||
val `application/xhtml+xml` = app("xhtml+xml", compressible, openEncoding)
|
||||
val `application/xml-dtd` = app("xml-dtd", compressible, openEncoding)
|
||||
val `application/xml` = app("xml", compressible, openEncoding)
|
||||
val `application/zip` = app("zip", uncompressible, binary, "zip")
|
||||
|
||||
val `audio/aiff` = aud("aiff", compressible, "aif", "aifc", "aiff")
|
||||
|
|
@ -384,7 +406,7 @@ object MediaTypes extends ObjectRegistry[(String, String), MediaType] {
|
|||
val `image/jpeg` = img("jpeg", uncompressible, binary, "jpe", "jpeg", "jpg")
|
||||
val `image/pict` = img("pict", compressible, binary, "pic", "pict")
|
||||
val `image/png` = img("png", uncompressible, binary, "png")
|
||||
val `image/svg+xml` = img("svg+xml", compressible, notBinary, "svg")
|
||||
val `image/svg+xml` = img("svg+xml", compressible, openEncoding, "svg")
|
||||
val `image/tiff` = img("tiff", compressible, binary, "tif", "tiff")
|
||||
val `image/x-icon` = img("x-icon", compressible, binary, "ico")
|
||||
val `image/x-ms-bmp` = img("x-ms-bmp", compressible, binary, "bmp")
|
||||
|
|
@ -481,4 +503,4 @@ object MediaTypes extends ObjectRegistry[(String, String), MediaType] {
|
|||
val `video/x-sgi-movie` = vid("x-sgi-movie", "movie", "mv")
|
||||
val `video/webm` = vid("webm", "webm")
|
||||
// format: ON
|
||||
}
|
||||
}
|
||||
|
|
@ -27,7 +27,8 @@ private[parser] trait CommonActions {
|
|||
case mainLower ⇒
|
||||
MediaTypes.getForKey((mainLower, subType.toRootLowerCase)) match {
|
||||
case Some(registered) ⇒ if (params.isEmpty) registered else registered.withParams(params)
|
||||
case None ⇒ MediaType.custom(mainType, subType, params = params, allowArbitrarySubtypes = true)
|
||||
case None ⇒ MediaType.custom(mainType, subType, encoding = MediaType.Encoding.Open,
|
||||
params = params, allowArbitrarySubtypes = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ class ResponseRendererSpec extends FreeSpec with Matchers with BeforeAndAfterAll
|
|||
|Server: akka-http/1.0.0
|
||||
|Date: Thu, 25 Aug 2011 09:10:29 GMT
|
||||
|Connection: close
|
||||
|Content-Type: application/json; charset=UTF-8
|
||||
|Content-Type: application/json
|
||||
|
|
||||
|""", close = true)
|
||||
}
|
||||
|
|
@ -184,7 +184,7 @@ class ResponseRendererSpec extends FreeSpec with Matchers with BeforeAndAfterAll
|
|||
|Server: akka-http/1.0.0
|
||||
|Date: Thu, 25 Aug 2011 09:10:29 GMT
|
||||
|Connection: close
|
||||
|Content-Type: application/json; charset=UTF-8
|
||||
|Content-Type: application/json
|
||||
|
|
||||
|abcdefg""", close = true)
|
||||
}
|
||||
|
|
@ -212,7 +212,7 @@ class ResponseRendererSpec extends FreeSpec with Matchers with BeforeAndAfterAll
|
|||
|Age: 30
|
||||
|Server: akka-http/1.0.0
|
||||
|Date: Thu, 25 Aug 2011 09:10:29 GMT
|
||||
|Content-Type: application/json; charset=UTF-8
|
||||
|Content-Type: application/json
|
||||
|
|
||||
|"""
|
||||
}
|
||||
|
|
@ -283,7 +283,7 @@ class ResponseRendererSpec extends FreeSpec with Matchers with BeforeAndAfterAll
|
|||
|Server: akka-http/1.0.0
|
||||
|Date: Thu, 25 Aug 2011 09:10:29 GMT
|
||||
|Connection: close
|
||||
|Content-Type: application/json; charset=UTF-8
|
||||
|Content-Type: application/json
|
||||
|
|
||||
|abcdefg""", close = true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import HttpEncodings._
|
|||
import HttpMethods._
|
||||
|
||||
class HttpHeaderSpec extends FreeSpec with Matchers {
|
||||
val `application/vnd.spray` = MediaType.custom("application/vnd.spray")
|
||||
val `application/vnd.spray` = MediaType.custom("application/vnd.spray", MediaType.Encoding.Binary)
|
||||
val PROPFIND = HttpMethod.custom("PROPFIND")
|
||||
|
||||
"The HTTP header model must correctly parse and render the headers" - {
|
||||
|
|
@ -36,9 +36,9 @@ class HttpHeaderSpec extends FreeSpec with Matchers {
|
|||
"Accept: */*, text/*; foo=bar, custom/custom; bar=\"b>az\"" =!=
|
||||
Accept(`*/*`,
|
||||
MediaRange.custom("text", Map("foo" -> "bar")),
|
||||
MediaType.custom("custom", "custom", params = Map("bar" -> "b>az")))
|
||||
MediaType.custom("custom", "custom", MediaType.Encoding.Binary, params = Map("bar" -> "b>az")))
|
||||
"Accept: application/*+xml; version=2" =!=
|
||||
Accept(MediaType.custom("application", "*+xml", params = Map("version" -> "2")))
|
||||
Accept(MediaType.custom("application", "*+xml", MediaType.Encoding.Binary, params = Map("version" -> "2")))
|
||||
}
|
||||
|
||||
"Accept-Charset" in {
|
||||
|
|
@ -190,8 +190,9 @@ class HttpHeaderSpec extends FreeSpec with Matchers {
|
|||
`Content-Type`(`application/pdf`)
|
||||
"Content-Type: text/plain; charset=utf8" =!=
|
||||
`Content-Type`(ContentType(`text/plain`, `UTF-8`)).renderedTo("text/plain; charset=UTF-8")
|
||||
"Content-Type: text/xml; version=3; charset=windows-1252" =!=
|
||||
`Content-Type`(ContentType(MediaType.custom("text", "xml", params = Map("version" -> "3")), HttpCharsets.getForKey("windows-1252")))
|
||||
"Content-Type: text/xml2; version=3; charset=windows-1252" =!=
|
||||
`Content-Type`(ContentType(MediaType.custom("text", "xml2", encoding = MediaType.Encoding.Open,
|
||||
params = Map("version" -> "3")), HttpCharsets.getForKey("windows-1252")))
|
||||
"Content-Type: text/plain; charset=fancy-pants" =!=
|
||||
`Content-Type`(ContentType(`text/plain`, HttpCharset.custom("fancy-pants")))
|
||||
"Content-Type: multipart/mixed; boundary=ABC123" =!=
|
||||
|
|
@ -199,7 +200,8 @@ class HttpHeaderSpec extends FreeSpec with Matchers {
|
|||
"Content-Type: multipart/mixed; boundary=\"ABC/123\"" =!=
|
||||
`Content-Type`(ContentType(`multipart/mixed` withBoundary "ABC/123"))
|
||||
"Content-Type: application/*" =!=
|
||||
`Content-Type`(ContentType(MediaType.custom("application", "*", allowArbitrarySubtypes = true)))
|
||||
`Content-Type`(ContentType(MediaType.custom("application", "*", MediaType.Encoding.Binary,
|
||||
allowArbitrarySubtypes = true)))
|
||||
}
|
||||
|
||||
"Content-Range" in {
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ class HttpModelIntegrationSpec extends WordSpec with Matchers with BeforeAndAfte
|
|||
}
|
||||
val textHeaders: Seq[(String, String)] = entityTextHeaders ++ partialTextHeaders
|
||||
textHeaders shouldEqual Seq(
|
||||
"Content-Type" -> "application/json; charset=UTF-8",
|
||||
"Content-Type" -> "application/json",
|
||||
"Content-Length" -> "5",
|
||||
"Host" -> "localhost",
|
||||
"Origin" -> "null")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue