Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
feat(api-v2): Improve error message when an XSLT transformation file …
…is not found (DSP-1404) (#1831)
  • Loading branch information
Benjamin Geer committed Mar 15, 2021
1 parent 7cd35de commit 153a674
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 35 deletions.
Expand Up @@ -23,6 +23,7 @@ import java.util.UUID

import akka.pattern._
import org.knora.webapi._
import org.knora.webapi.exceptions.{NotFoundException, SipiException}
import org.knora.webapi.feature.FeatureFactoryConfig
import org.knora.webapi.messages.IriConversions._
import org.knora.webapi.messages.StringFormatter
Expand Down Expand Up @@ -72,7 +73,7 @@ class StandoffResponderV1(responderData: ResponderData) extends Responder(respon
featureFactoryConfig: FeatureFactoryConfig,
userProfile: UserADM): Future[GetXSLTransformationResponseV1] = {

for {
val xslTransformationFuture = for {
xsltTransformation <- (responderManager ? GetXSLTransformationRequestV2(
xsltTextRepresentationIri = xslTransformationIri,
featureFactoryConfig = featureFactoryConfig,
Expand All @@ -82,6 +83,13 @@ class StandoffResponderV1(responderData: ResponderData) extends Responder(respon
GetXSLTransformationResponseV1(
xslt = xsltTransformation.xslt
)

xslTransformationFuture.recover {
case notFound: NotFoundException =>
throw SipiException(s"XSL transformation $xslTransformationIri not found: ${notFound.message}")

case other => throw other
}
}

/**
Expand Down
Expand Up @@ -1770,11 +1770,18 @@ class ResourcesResponderV2(responderData: ResponderData) extends ResponderWithSt
requestingUser = requestingUser
)

for {
val xslTransformationFuture = for {
xslTransformation: GetXSLTransformationResponseV2 <- (responderManager ? teiHeaderXsltRequest)
.mapTo[GetXSLTransformationResponseV2]
} yield Some(xslTransformation.xslt)

xslTransformationFuture.recover {
case notFound: NotFoundException =>
throw SipiException(s"TEI header XSL transformation <$headerIri> not found: ${notFound.message}")

case other => throw other
}

case None => Future(None)
}

Expand Down Expand Up @@ -1819,11 +1826,18 @@ class ResourcesResponderV2(responderData: ResponderData) extends ResponderWithSt
requestingUser = requestingUser
)

for {
val xslTransformationFuture = for {
xslTransformation: GetXSLTransformationResponseV2 <- (responderManager ? teiBodyXsltRequest)
.mapTo[GetXSLTransformationResponseV2]
} yield xslTransformation.xslt

xslTransformationFuture.recover {
case notFound: NotFoundException =>
throw SipiException(
s"Default XSL transformation <${teiMapping.mapping.defaultXSLTransformation.get}> not found for mapping <${teiMapping.mappingIri}>: ${notFound.message}")

case other => throw other
}
case None => throw BadRequestException(s"Default XSL Transformation expected for mapping $otherMapping")
}
}
Expand Down
Expand Up @@ -19,8 +19,10 @@

package org.knora.webapi.responders.v2

import akka.http.scaladsl.util.FastFuture
import akka.pattern._
import org.knora.webapi.IRI
import org.knora.webapi.exceptions.{NotFoundException, SipiException}
import org.knora.webapi.feature.FeatureFactoryConfig
import org.knora.webapi.messages.admin.responder.usersmessages.UserADM
import org.knora.webapi.messages.util.ConstructResponseUtilV2.{MappingAndXSLTransformation, ResourceWithValueRdfData}
Expand Down Expand Up @@ -79,15 +81,23 @@ abstract class ResponderWithStandoffV2(responderData: ResponderData) extends Res
for {
// if given, get the default XSL transformation
xsltOption: Option[String] <- if (mapping.mapping.defaultXSLTransformation.nonEmpty) {
for {
val xslTransformationFuture = for {
xslTransformation: GetXSLTransformationResponseV2 <- (responderManager ? GetXSLTransformationRequestV2(
mapping.mapping.defaultXSLTransformation.get,
featureFactoryConfig = featureFactoryConfig,
requestingUser = requestingUser
)).mapTo[GetXSLTransformationResponseV2]
} yield Some(xslTransformation.xslt)

xslTransformationFuture.recover {
case notFound: NotFoundException =>
throw SipiException(
s"Default XSL transformation <${mapping.mapping.defaultXSLTransformation.get}> not found for mapping <${mapping.mappingIri}>: ${notFound.message}")

case other => throw other
}
} else {
Future(None)
FastFuture.successful(None)
}
} yield
mapping.mappingIri -> MappingAndXSLTransformation(mapping = mapping.mapping,
Expand Down
Expand Up @@ -31,7 +31,7 @@ import org.apache.http.impl.client.{CloseableHttpClient, HttpClients}
import org.apache.http.message.BasicNameValuePair
import org.apache.http.util.EntityUtils
import org.apache.http.{Consts, HttpHost, HttpRequest, NameValuePair}
import org.knora.webapi.exceptions.{BadRequestException, SipiException}
import org.knora.webapi.exceptions.{BadRequestException, NotFoundException, SipiException}
import org.knora.webapi.messages.StringFormatter
import org.knora.webapi.messages.store.sipimessages._
import org.knora.webapi.messages.v2.responder.SuccessResponseV2
Expand Down Expand Up @@ -221,14 +221,24 @@ class SipiConnector extends Actor with ActorLogging {
} yield SipiGetTextFileResponse(responseStr)

sipiResponseTry.recover {
case notFoundException: NotFoundException =>
throw NotFoundException(
s"Unable to get file ${textFileRequest.fileUrl} from Sipi as requested by ${textFileRequest.senderName}: ${notFoundException.message}")

case badRequestException: BadRequestException =>
throw SipiException(
s"Unable to get file ${textFileRequest.fileUrl} from Sipi as requested by ${textFileRequest.senderName}: ${badRequestException.message}")

case sipiException: SipiException =>
throw SipiException(
s"Unable to get file ${textFileRequest.fileUrl} from Sipi as requested by ${textFileRequest.senderName}: ${sipiException.message}",
sipiException.cause
)

case other =>
throw SipiException(
s"Unable to get file ${textFileRequest.fileUrl} from Sipi as requested by ${textFileRequest.senderName}: ${other.getMessage}"
)
}
}

Expand All @@ -254,45 +264,45 @@ class SipiConnector extends Actor with ActorLogging {
*/
private def doSipiRequest(request: HttpRequest): Try[String] = {
val httpContext: HttpClientContext = HttpClientContext.create
var maybeResponse: Option[CloseableHttpResponse] = None

val sipiResponseTry = Try {
var maybeResponse: Option[CloseableHttpResponse] = None

try {
maybeResponse = Some(httpClient.execute(targetHost, request, httpContext))
maybeResponse = Some(httpClient.execute(targetHost, request, httpContext))

val responseEntityStr: String = Option(maybeResponse.get.getEntity) match {
case Some(responseEntity) => EntityUtils.toString(responseEntity)
case None => ""
}

val statusCode: Int = maybeResponse.get.getStatusLine.getStatusCode
val statusCategory: Int = statusCode / 100
val responseEntityStr: String = Option(maybeResponse.get.getEntity) match {
case Some(responseEntity) => EntityUtils.toString(responseEntity)
case None => ""
}

// Was the request successful?
if (statusCategory == 2) {
// Yes.
responseEntityStr
val statusCode: Int = maybeResponse.get.getStatusLine.getStatusCode
val statusCategory: Int = statusCode / 100

// Was the request successful?
if (statusCategory == 2) {
// Yes.
responseEntityStr
} else {
// No. Throw an appropriate exception.
val sipiErrorMsg = SipiUtil.getSipiErrorMessage(responseEntityStr)

if (statusCode == 404) {
throw NotFoundException(sipiErrorMsg)
} else if (statusCategory == 4) {
throw BadRequestException(s"Sipi responded with HTTP status code $statusCode: $sipiErrorMsg")
} else {
// No. Throw an appropriate exception.
val sipiErrorMsg = SipiUtil.getSipiErrorMessage(responseEntityStr)

if (statusCategory == 4) {
throw BadRequestException(s"Sipi responded with HTTP status code $statusCode: $sipiErrorMsg")
} else {
throw SipiException(s"Sipi responded with HTTP status code $statusCode: $sipiErrorMsg")
}
}
} finally {
maybeResponse match {
case Some(response) => response.close()
case None => ()
throw SipiException(s"Sipi responded with HTTP status code $statusCode: $sipiErrorMsg")
}
}
}

maybeResponse match {
case Some(response) => response.close()
case None => ()
}

sipiResponseTry.recover {
case badRequestException: BadRequestException => throw badRequestException
case notFoundException: NotFoundException => throw notFoundException
case sipiException: SipiException => throw sipiException
case e: Exception => throw SipiException("Failed to connect to Sipi", e, log)
}
Expand Down
Expand Up @@ -729,7 +729,7 @@ class KnoraSipiIntegrationV1ITSpec
Await.result(response.entity.toStrict(2.seconds).map(_.data.decodeString("UTF-8")), 2.seconds)
assert(responseBodyStr.contains("Unable to get file"))
assert(responseBodyStr.contains("as requested by org.knora.webapi.responders.v2.StandoffResponderV2"))
assert(responseBodyStr.contains("Sipi responded with HTTP status code 404"))
assert(responseBodyStr.contains("Not Found"))
}

"create a resource with a PDF file attached" in {
Expand Down

0 comments on commit 153a674

Please sign in to comment.