Skip to content

Commit

Permalink
Return 404 for missing mosaics
Browse files Browse the repository at this point in the history
Closes #859
  • Loading branch information
jisantuc committed Aug 30, 2021
1 parent 56a8e7b commit 0c073f9
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.azavea.franklin.api.endpoints.{
SearchEndpoints,
TileEndpoints
}
import com.azavea.franklin.api.middleware.AccessLoggingMiddleware
import com.azavea.franklin.api.services._
import com.azavea.franklin.extensions.validation.{collectionExtensionsRef, itemExtensionsRef}
import com.azavea.stac4s.{`application/json`, StacLink, StacLinkType}
Expand All @@ -35,7 +36,6 @@ import scala.concurrent.ExecutionContext

import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
import com.azavea.franklin.api.middleware.AccessLoggingMiddleware

object Server extends IOApp.WithContext {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,12 @@ class TileEndpoints[F[_]: Concurrent](enableTiles: Boolean, pathPrefix: Option[S
.name("collectionFootprintTileJSON")

val collectionMosaicEndpoint
: Endpoint[CollectionMosaicRequest, Unit, Array[Byte], Fs2Streams[F]] =
: Endpoint[CollectionMosaicRequest, NotFound, Array[Byte], Fs2Streams[F]] =
endpoint.get
.in(collectionRasterTileParameters)
.out(rawBinaryBody[Array[Byte]])
.out(header("content-type", "image/png"))
.errorOut(oneOf(statusMapping(NF, jsonBody[NotFound].description("not found"))))
.description(
"Raster tile endpoint for collection mosaic"
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package com.azavea.franklin.api.middleware

import cats.data.Kleisli
import cats.data.OptionT
import cats.effect.Sync
import cats.syntax.functor._
import io.chrisdavenport.log4cats.Logger
import io.circe.syntax._
import org.http4s.util.CaseInsensitiveString
import org.http4s.{HttpRoutes, Request}

import java.time.Instant
import io.chrisdavenport.log4cats.Logger
import cats.data.OptionT

class AccessLoggingMiddleware[F[_]: Sync](
service: HttpRoutes[F],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,56 +196,57 @@ class TileService[F[_]: Async: Concurrent: Parallel: Logger: Timer: ContextShift

def getCollectionMosaicTile(
tileRequest: CollectionMosaicRequest
): F[Either[Unit, Array[Byte]]] = {
): F[Either[NF, Array[Byte]]] = {
val (z, x, y) = tileRequest.zxy

for {
itemAssets <- getItemsList(tileRequest.collection, tileRequest.mosaicId, z, x, y)
_ <- Logger[F].debug(s"got items list with ${itemAssets.size} items")
assetHrefs <- itemAssets.parTraverseN(8) {
case ItemAsset(itemId, assetName) =>
getItemsList(tileRequest.collection, tileRequest.mosaicId, z, x, y) flatMap { itemAssets =>
itemAssets.toNel.fold(Either.left[NF, Array[Byte]](NF()).pure[F])(
(itemAssets: NonEmptyList[ItemAsset]) =>
for {
() <- Logger[F].debug(s"getting asset ${itemId}-${assetName}")
asset <- StacItemDao.unsafeGetAsset(itemId, assetName).transact(xa)
() <- Logger[F].debug(s"got asset ${itemId}-${assetName}")
} yield asset
}
histO <- getHistogram(tileRequest.mosaicId)
mosaicSource <- assetHrefs traverse { asset =>
getRasterSource(asset.href)
} map { sources =>
sources.toNel map { rs => MosaicRasterSource(rs, CRS.fromEpsgCode(3857)) }
}
tileO <- mosaicSource flatTraverse { rs =>
Sync[F].delay(
rs.tileToLayout(tmsLevels(tileRequest.z))
.read(SpatialKey(x, y), tileRequest.bands)
)
}
} yield {
val outCellTypeWithNoData =
mosaicSource
.flatMap({ src => getNoDataValue(src.cellType) map { _ => src.cellType } })
.fold(invisiCellType: CellType)(identity)
val outTile = (tileO, histO) mapN {
case (mbt, hists) =>
MultibandTile(mbt.bands.zip(hists).map {
case (tile, histogram) =>
val breaks = histogram.quantileBreaks(100)
val oldMin = breaks(tileRequest.lowerQuantile)
val oldMax = breaks(tileRequest.upperQuantile)
tile
.interpretAs(outCellTypeWithNoData)
.mapIfSet { cell =>
if (cell < oldMin) oldMin
else if (cell > oldMax) oldMax
else cell
}
.normalize(oldMin, oldMax, 1, 255)
_ <- Logger[F].debug(s"got items list with ${itemAssets.size} items")
assetHrefs <- itemAssets.parTraverseN(8) {
case ItemAsset(itemId, assetName) =>
for {
() <- Logger[F].debug(s"getting asset ${itemId}-${assetName}")
asset <- StacItemDao.unsafeGetAsset(itemId, assetName).transact(xa)
() <- Logger[F].debug(s"got asset ${itemId}-${assetName}")
} yield asset
}
histO <- getHistogram(tileRequest.mosaicId)
mosaicSource <- assetHrefs traverse { asset =>
getRasterSource(asset.href)
} map { sources => MosaicRasterSource(sources, CRS.fromEpsgCode(3857)) }
tileO <- Sync[F].delay(
mosaicSource
.tileToLayout(tmsLevels(tileRequest.z))
.read(SpatialKey(x, y), tileRequest.bands)
)
} yield {
val outCellTypeWithNoData =
getNoDataValue(mosaicSource.cellType).fold(invisiCellType: CellType)(_ =>
mosaicSource.cellType
)
val outTile = (tileO, histO) mapN {
case (mbt, hists) =>
MultibandTile(mbt.bands.zip(hists).map {
case (tile, histogram) =>
val breaks = histogram.quantileBreaks(100)
val oldMin = breaks(tileRequest.lowerQuantile)
val oldMax = breaks(tileRequest.upperQuantile)
tile
.interpretAs(outCellTypeWithNoData)
.mapIfSet { cell =>
if (cell < oldMin) oldMin
else if (cell > oldMax) oldMax
else cell
}
.normalize(oldMin, oldMax, 1, 255)

})
} getOrElse invisiMBTile
Right(outTile.renderPng.bytes)
})
} getOrElse invisiMBTile
Right(outTile.renderPng.bytes)
}
)
}
}

Expand Down

0 comments on commit 0c073f9

Please sign in to comment.