diff --git a/CHANGELOG.unreleased.md b/CHANGELOG.unreleased.md index 0dfeedfed29..71e78115837 100644 --- a/CHANGELOG.unreleased.md +++ b/CHANGELOG.unreleased.md @@ -19,6 +19,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released - Searching the segments in the sidebar will highlight newly focused segments properly now. [#7406](https://github.com/scalableminds/webknossos/pull/7406) - Fixed a bug when opening a task for which a mag restriction exists. The bug only occurred when the referenced mag didn't exist in the dataset. [#7403](https://github.com/scalableminds/webknossos/pull/7403) - Fixed styling issues with the maintenance banner so that it no longer overlaps other menus, tabs, and buttons. [#7421](https://github.com/scalableminds/webknossos/pull/7421) +- Exploring HTTP uris of unknown hosts no longer causes an exception error message to be displayed. [#7422](https://github.com/scalableminds/webknossos/pull/7422) ### Removed diff --git a/util/src/main/scala/com/scalableminds/util/tools/Fox.scala b/util/src/main/scala/com/scalableminds/util/tools/Fox.scala index c832423bfc3..a92a8a9a100 100644 --- a/util/src/main/scala/com/scalableminds/util/tools/Fox.scala +++ b/util/src/main/scala/com/scalableminds/util/tools/Fox.scala @@ -242,6 +242,18 @@ object Fox extends FoxImplicits { failure.msg + formatStackTrace(failure) + formatChain(failure.chain) } + + /** + * Transform a Future[T] into a Fox[T] such that if the Future contains an exception, it is turned into a Fox.failure + */ + def transformFuture[T](future: Future[T])(implicit ec: ExecutionContext): Fox[T] = + for { + fut <- future.transform { + case Success(value) => Try(Fox.successful(value)) + case scala.util.Failure(e) => Try(Fox.failure(e.getMessage, Full(e))) + } + f <- fut + } yield f } class Fox[+A](val futureBox: Future[Box[A]])(implicit ec: ExecutionContext) { diff --git a/webknossos-datastore/app/com/scalableminds/webknossos/datastore/datavault/HttpsDataVault.scala b/webknossos-datastore/app/com/scalableminds/webknossos/datastore/datavault/HttpsDataVault.scala index db769dd342e..9ef1bf7871e 100644 --- a/webknossos-datastore/app/com/scalableminds/webknossos/datastore/datavault/HttpsDataVault.scala +++ b/webknossos-datastore/app/com/scalableminds/webknossos/datastore/datavault/HttpsDataVault.scala @@ -50,7 +50,7 @@ class HttpsDataVault(credential: Option[DataVaultCredential], ws: WSClient) exte headerInfoCache.getOrLoad( uri, { uri => for { - response <- ws.url(uri.toString).withRequestTimeout(readTimeout).head() + response <- Fox.transformFuture(ws.url(uri.toString).withRequestTimeout(readTimeout).head()) acceptsPartialRequests = response.headerValues("Accept-Ranges").contains("bytes") dataSize = response.header("Content-Length").map(_.toLong).getOrElse(0L) } yield (acceptsPartialRequests, dataSize) @@ -60,19 +60,20 @@ class HttpsDataVault(credential: Option[DataVaultCredential], ws: WSClient) exte private def getWithRange(uri: URI, range: NumericRange[Long])(implicit ec: ExecutionContext): Fox[WSResponse] = for { _ <- ensureRangeRequestsSupported(uri) - response <- buildRequest(uri).withHttpHeaders("Range" -> s"bytes=${range.start}-${range.end - 1}").get() + response <- Fox.transformFuture( + buildRequest(uri).withHttpHeaders("Range" -> s"bytes=${range.start}-${range.end - 1}").get()) _ = updateRangeRequestsSupportedForResponse(response) } yield response private def getWithSuffixRange(uri: URI, length: Long)(implicit ec: ExecutionContext): Fox[WSResponse] = for { _ <- ensureRangeRequestsSupported(uri) - response <- buildRequest(uri).withHttpHeaders("Range" -> s"bytes=-$length").get() + response <- Fox.transformFuture(buildRequest(uri).withHttpHeaders("Range" -> s"bytes=-$length").get()) _ = updateRangeRequestsSupportedForResponse(response) } yield response private def getComplete(uri: URI)(implicit ec: ExecutionContext): Fox[WSResponse] = - buildRequest(uri).get() + Fox.transformFuture(buildRequest(uri).get()) private def ensureRangeRequestsSupported(uri: URI)(implicit ec: ExecutionContext): Fox[Unit] = for {