From 78f0231e9a653841d5838c3859f09aea9002d04a Mon Sep 17 00:00:00 2001 From: Fabian Engelniederhammer Date: Wed, 23 Aug 2023 10:30:38 +0200 Subject: [PATCH] feat: enable for operating behind a proxy that modifies the url Assume the backend is hosted on a server with a proxy that maps requests to `/backend/` to `/`, then we need a mechanism so that links still work (the link from the error page to the swagger UI, the links in the swagger UI to the api docs). This solution assumes that `X-forwarded-...` headers are set by the proxy, e.g.: * X-Forwarded-For * X-Forwarded-Proto * X-Forwarded-Prefix --- lapis2/README.md | 7 +++ .../lapis/controller/ErrorController.kt | 63 +++++++++++++++++++ .../src/main/resources/public/error/404.html | 12 ---- siloLapisTests/test/unknownUrl.spec.ts | 2 +- 4 files changed, 71 insertions(+), 13 deletions(-) create mode 100644 lapis2/src/main/kotlin/org/genspectrum/lapis/controller/ErrorController.kt delete mode 100644 lapis2/src/main/resources/public/error/404.html diff --git a/lapis2/README.md b/lapis2/README.md index 68526ef9..27614f19 100644 --- a/lapis2/README.md +++ b/lapis2/README.md @@ -34,6 +34,13 @@ Use Docker Compose to run SILO and LAPIS: LAPIS_TAG=latest SILO_TAG=latest DATABASE_CONFIG=path/to/config docker compose up ``` +### Operating LAPIS behind a proxy + +When running LAPIS behind a proxy, the proxy needs to set X-Forwarded headers: +* X-Forwarded-For +* X-Forwarded-Proto +* X-Forwarded-Prefix + ## End-to-end tests There are end-to-end tests in `siloLapisTests/` that test the integration of SILO and LAPIS. diff --git a/lapis2/src/main/kotlin/org/genspectrum/lapis/controller/ErrorController.kt b/lapis2/src/main/kotlin/org/genspectrum/lapis/controller/ErrorController.kt new file mode 100644 index 00000000..c0d002fe --- /dev/null +++ b/lapis2/src/main/kotlin/org/genspectrum/lapis/controller/ErrorController.kt @@ -0,0 +1,63 @@ +package org.genspectrum.lapis.controller + +import jakarta.servlet.http.HttpServletRequest +import jakarta.servlet.http.HttpServletResponse +import mu.KotlinLogging +import org.springframework.boot.autoconfigure.web.ErrorProperties +import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController +import org.springframework.boot.web.servlet.error.ErrorAttributes +import org.springframework.http.MediaType +import org.springframework.stereotype.Component +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.servlet.ModelAndView +import org.springframework.web.servlet.View +import org.springframework.web.servlet.support.ServletUriComponentsBuilder + +private val log = KotlinLogging.logger { } + +@Component +class ErrorController(errorAttributes: ErrorAttributes) : + BasicErrorController(errorAttributes, ErrorProperties()) { + + @RequestMapping(produces = [MediaType.TEXT_HTML_VALUE]) + override fun errorHtml(request: HttpServletRequest, response: HttpServletResponse): ModelAndView { + val modelAndView = super.errorHtml(request, response) + + response.addHeader("Content-Type", MediaType.TEXT_HTML_VALUE) + + val urlPrefix = removeErrorSegmentFromUrl(ServletUriComponentsBuilder.fromCurrentRequest().toUriString()) + val url = "$urlPrefix/swagger-ui/index.html" + + log.debug { "Generated url $url to Swagger UI in 'not found page'" } + + modelAndView.view = NotFoundView(url) + return modelAndView + } + + fun removeErrorSegmentFromUrl(url: String): String { + val lastSlashIndex = url.trimEnd('/').lastIndexOf("error") + return url.substring(0, lastSlashIndex).trim('/') + } +} + +data class NotFoundView(private val url: String?) : View { + + override fun render(model: MutableMap?, request: HttpServletRequest, response: HttpServletResponse) { + val html: String = """ + + + + + Error 404 + + +

LAPIS

+

Page not found!

+ Visit our swagger-ui + + + """.trimIndent() + + response.outputStream.write(html.toByteArray()) + } +} diff --git a/lapis2/src/main/resources/public/error/404.html b/lapis2/src/main/resources/public/error/404.html deleted file mode 100644 index fe18d3e3..00000000 --- a/lapis2/src/main/resources/public/error/404.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - Error 404 - - -

LAPIS

-

Page not found!

- Visit our swagger-ui - - diff --git a/siloLapisTests/test/unknownUrl.spec.ts b/siloLapisTests/test/unknownUrl.spec.ts index 90c571e9..a5f86d5f 100644 --- a/siloLapisTests/test/unknownUrl.spec.ts +++ b/siloLapisTests/test/unknownUrl.spec.ts @@ -18,6 +18,6 @@ describe('Error handling: UnknownUrl', () => { let responseBody = await result.text(); expect(responseBody).contains('Page not found'); - expect(responseBody).contains('a href="/swagger-ui/index.html"'); + expect(responseBody).contains(''); }); });