Skip to content

Commit 1f198da

Browse files
authored
Merge pull request http4s/http4s-scala-xml#28 from http4s/load-xml-is-blocking
Mark the loadXML call as blocking
2 parents c315f5d + d82d827 commit 1f198da

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

docs/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class JsonXmlHttpEndpoint[F[_]](implicit F: Async[F]) extends Http4sDsl[F] {
3838
}
3939

4040
private def personXmlDecoder: EntityDecoder[F, Person] =
41-
org.http4s.scalaxml.xml[F].map(Person.fromXml)
41+
org.http4s.scalaxml.xmlDecoder[F].map(Person.fromXml)
4242

4343
implicit private def jsonXmlDecoder: EntityDecoder[F, Person] =
4444
jsonOf[F, Person].orElse(personXmlDecoder)
@@ -55,4 +55,4 @@ class JsonXmlHttpEndpoint[F[_]](implicit F: Async[F]) extends Http4sDsl[F] {
5555
}
5656
}
5757
}
58-
```
58+
```

scala-xml/src/main/scala/org/http4s/scalaxml/ElemInstances.scala

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717
package org.http4s
1818
package scalaxml
1919

20+
import cats.data.EitherT
21+
import cats.effect.Async
2022
import cats.effect.Concurrent
23+
import cats.syntax.all._
2124
import org.http4s.Charset.`UTF-8`
2225
import org.http4s.headers.`Content-Type`
2326

@@ -49,7 +52,8 @@ trait ElemInstances {
4952
*
5053
* @return an XML element
5154
*/
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] = {
5357
import EntityDecoder._
5458
decodeBy(MediaType.text.xml, MediaType.text.html, MediaType.application.xml) { msg =>
5559
val source = new InputSource()
@@ -67,4 +71,25 @@ trait ElemInstances {
6771
}
6872
}
6973
}
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+
7095
}

0 commit comments

Comments
 (0)