From 1df24888b43d3c54ed5f4bd83428be77e383edb6 Mon Sep 17 00:00:00 2001 From: Mike Bryant Date: Fri, 15 Mar 2024 11:52:15 +0000 Subject: [PATCH] Hack the Search API error handler to figure out moved units This requires an unseemly substitution of the API URL prefix with the /unit one, so it won't work for types of item yet. That will have to wait for a better solution. --- modules/api/app/controllers/api/v1/ApiV1.scala | 18 +++++++++++++++++- modules/api/conf/messages | 2 ++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/modules/api/app/controllers/api/v1/ApiV1.scala b/modules/api/app/controllers/api/v1/ApiV1.scala index 3a7d8a539d..754ec6fa5b 100644 --- a/modules/api/app/controllers/api/v1/ApiV1.scala +++ b/modules/api/app/controllers/api/v1/ApiV1.scala @@ -21,6 +21,7 @@ import services.RateLimitChecker import services.accounts.AccountManager import services.cypher.CypherService import services.data._ +import services.redirects.MovedPageLookup import services.search.SearchConstants._ import services.search._ import utils.{DateFacetUtils, FieldFilter, Page, PageParams} @@ -55,6 +56,7 @@ case class ApiV1 @Inject()( ws: WSClient, cypher: CypherService, rateLimits: RateLimitChecker, + pageRelocator: MovedPageLookup, mat: Materializer, dfu: DateFacetUtils ) extends CoreActionBuilders @@ -495,7 +497,21 @@ case class ApiV1 @Inject()( immediate(Redirect(controllers.api.routes.ApiHome.index())) private def errorHandler(implicit request: RequestHeader): PartialFunction[Throwable, Future[Result]] = { - case e: ItemNotFound => immediate(error(NOT_FOUND, e.message)) + case e: ItemNotFound => + // FIXME: + // This is a hack because we store moved items by the hash of their page URL so we can't + // easily determine if an item has moved when the API location isn't stored. Here is + // a heuristic to check if a Documentary Unit has been moved, via the hard-coded /units URL. + // Unlikely this ever changes now but if it does this will break. + // If/when the redirect DB is updated to store item IDs this can be reworked. + val unitPrefix = "/units" + val unitPath = request.path.replace(routes.ApiV1Home.index().url, unitPrefix) + pageRelocator.hasMovedTo(unitPath).map { + case Some(newPath) => + val newApiPath = newPath.replace(unitPrefix, routes.ApiV1Home.index().url) + error(MOVED_PERMANENTLY, Some(newApiPath)).withHeaders(HeaderNames.LOCATION -> newApiPath) + case None => error(NOT_FOUND, e.message) + } case e: PermissionDenied => immediate(error(FORBIDDEN)) case _ => immediate(error(INTERNAL_SERVER_ERROR)) } diff --git a/modules/api/conf/messages b/modules/api/conf/messages index e2a566ea52..22964729af 100644 --- a/modules/api/conf/messages +++ b/modules/api/conf/messages @@ -1,3 +1,5 @@ +api.error.301=Moved Permanently +api.error.302=Found api.error.400=Bad Request api.error.401=Not Authenticated api.error.403=Forbidden