17
17
package org .http4s
18
18
package scalaxml
19
19
20
+ import cats .data .EitherT
21
+ import cats .effect .Async
20
22
import cats .effect .Concurrent
23
+ import cats .syntax .all ._
21
24
import org .http4s .Charset .`UTF-8`
22
25
import org .http4s .headers .`Content-Type`
23
26
@@ -49,7 +52,8 @@ trait ElemInstances {
49
52
*
50
53
* @return an XML element
51
54
*/
52
- implicit def xml [F [_]](implicit F : Concurrent [F ]): EntityDecoder [F , Elem ] = {
55
+ @ deprecated(" Blocks. Use xmlDecoder with an Async constraint." , " 0.23.12" )
56
+ def xml [F [_]](implicit F : Concurrent [F ]): EntityDecoder [F , Elem ] = {
53
57
import EntityDecoder ._
54
58
decodeBy(MediaType .text.xml, MediaType .text.html, MediaType .application.xml) { msg =>
55
59
val source = new InputSource ()
@@ -67,4 +71,25 @@ trait ElemInstances {
67
71
}
68
72
}
69
73
}
74
+
75
+ implicit def xmlDecoder [F [_]](implicit F : Async [F ]): EntityDecoder [F , Elem ] = {
76
+ import EntityDecoder ._
77
+ decodeBy(MediaType .text.xml, MediaType .text.html, MediaType .application.xml) { msg =>
78
+ val source = new InputSource ()
79
+ msg.charset.foreach(cs => source.setEncoding(cs.nioCharset.name))
80
+
81
+ collectBinary(msg).flatMap[DecodeFailure , Elem ] { chunk =>
82
+ source.setByteStream(new ByteArrayInputStream (chunk.toArray))
83
+ val saxParser = saxFactory.newSAXParser()
84
+ EitherT (
85
+ F .blocking(XML .loadXML(source, saxParser))
86
+ .map(Either .right[DecodeFailure , Elem ](_))
87
+ .recover { case e : SAXParseException =>
88
+ Left (MalformedMessageBodyFailure (" Invalid XML" , Some (e)))
89
+ }
90
+ )
91
+ }
92
+ }
93
+ }
94
+
70
95
}
0 commit comments