in app/controllers/Application.scala [57:130]
private def rawRss(tagId: String, userApiKey: Option[String]): Future[Result] = {
val client = new CustomCapiClient(apiKey)
val maxItems = 300
val pageSize = 100
val query = ItemQuery(tagId)
.showElements("audio,image")
.showTags("keyword")
.showFields("webTitle,webPublicationDate,standfirst,trailText,internalComposerCode")
def fetchItemsWithPagination(query: ItemQuery, page: Int = 1, resps: Seq[ItemResponse] = Seq.empty): Future[Seq[ItemResponse]] = {
logger.debug("Fetching page: " + page + " with page size: " + pageSize)
val withPagination = query.page(page).pageSize(pageSize)
client.getResponse(withPagination).flatMap { resp =>
val responses = resps :+ resp
// Paginate if we have not covered the required number of pages and there are more pages available
val lastRequiredPage = (maxItems / pageSize) + (if (maxItems % pageSize > 0) { 1 } else { 0 })
val shouldPaginate = (page < lastRequiredPage) && resp.pages.getOrElse(0) > page
if (shouldPaginate) {
// Recurse with the results and pagination incremented
fetchItemsWithPagination(query, page + 1, responses)
} else {
logger.info("Finished fetching " + responses.map(_.results.map(_.size).getOrElse(0)).sum + " items after paginating to page " + page)
Future.successful(responses)
}
}
}
(for {
itemResponses <- fetchItemsWithPagination(query)
userApiKeyTier <- userApiKey.map { userApiKey =>
// If an external partner has identified themselves using an api-key we will query to resolve the user tier
new CustomCapiClient(userApiKey).getResponse(ItemQuery(tagId).pageSize(0)).map { resp =>
Some(resp.userTier)
}
}.getOrElse {
Future.successful(None)
}
} yield {
// If all item responses were ok then we can render a result
if (itemResponses.forall(_.status == "ok")) {
val isAdFree = userApiKeyTier.contains("rights-managed")
iTunesRssFeed(itemResponses, isAdFree, imageResizerSignatureSalt) match {
case Good(xml) =>
val now = DateTime.now()
val expiresTime = now.plusSeconds(maxAge)
Ok(xml).withHeaders(
"Surrogate-Control" -> cacheControl,
"Cache-Control" -> cacheControl,
"Expires" -> expiresTime.toString(HTTPDateFormat),
"Date" -> now.toString(HTTPDateFormat))
case Bad(failed: Failed) =>
logger.warn(s"Failed to render XML. tagId = $tagId, ${failed.toString}")
failed.status
}
} else {
NotFound
}
}).recover {
case ContentApiError(404, _, _) => NotFound
case ContentApiError(403, _, _) => Forbidden
case ContentApiError(401, _, _) => Unauthorized
// maybe this generic InternalServerError could be a better representation of the CAPI failure mode
case ContentApiError(status, msg, errorResponse) =>
logger.warn(s"Unexpected response code from CAPI. tagId = $tagId, HTTP status = $status, error response = $errorResponse")
InternalServerError
}