Reputation: 3463
I have the following method that returns a Future[Source[List[String]]]
(the first two lines of a CSV file):
def get(url: String, charset: String, delimiter: Char, quote: Char, escape: Char) = {
val scanner = CsvParsing.lineScanner(
delimiter.toByte,
quote.toByte,
escape.toByte
)
val request = HttpRequest(GET, Uri(url)).withHeaders(`User-Agent`(UserAgent))
Http(system)
.singleRequest(request)
.map { response =>
response.entity.withoutSizeLimit.dataBytes
.viaMat(scanner)(Keep.left)
.map(row =>
row.map(bs =>
bs.decodeString(charset)
)
)
.take(2)
}
}
The returned Future
is passed to complete
, which marshals it to a JSON array of arrays using:
implicit val jsonStreamingSupport: JsonEntityStreamingSupport = EntityStreamingSupport.json()
However, I'd like to inspect response
and return a different HttpResponse
if it isn't a 200. It seems like the best way to do this would be to marshal the Future[Source[...]]
to an HttpResponse
in this method, and then its return type would be HttpResponse
either way.
How do I do that? Or is there a better way?
Upvotes: 2
Views: 492
Reputation: 3463
Okay, so I got there in the end with a different approach.
Http(system).singleRequest(request)
.flatMap { response =>
response.status match {
case StatusCodes.OK =>
val compression = CompressionChooser.choose(url, gzip, response)
response.entity.withoutSizeLimit.dataBytes
.via(compression.decoder.decoderFlow)
.viaMat(scanner)(Keep.left)
.map(_.map(_.decodeString(charset)))
.take(2)
.runWith(Sink.seq)
.map { rows =>
val json = Json.toJson(rows)
HttpResponse(
StatusCodes.OK,
entity = HttpEntity(ContentTypes.`application/json`, json.toString)
)
}
case _ => Future successful HttpResponse(StatusCodes.BadRequest, entity = "Error")
}
}
Upvotes: 1