Skip to content

Commit 78f0231

Browse files
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/<routes>` to `/<routes>`, 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
1 parent 5a6e856 commit 78f0231

File tree

4 files changed

+71
-13
lines changed

4 files changed

+71
-13
lines changed

lapis2/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ Use Docker Compose to run SILO and LAPIS:
3434
LAPIS_TAG=latest SILO_TAG=latest DATABASE_CONFIG=path/to/config docker compose up
3535
```
3636

37+
### Operating LAPIS behind a proxy
38+
39+
When running LAPIS behind a proxy, the proxy needs to set X-Forwarded headers:
40+
* X-Forwarded-For
41+
* X-Forwarded-Proto
42+
* X-Forwarded-Prefix
43+
3744
## End-to-end tests
3845

3946
There are end-to-end tests in `siloLapisTests/` that test the integration of SILO and LAPIS.
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package org.genspectrum.lapis.controller
2+
3+
import jakarta.servlet.http.HttpServletRequest
4+
import jakarta.servlet.http.HttpServletResponse
5+
import mu.KotlinLogging
6+
import org.springframework.boot.autoconfigure.web.ErrorProperties
7+
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController
8+
import org.springframework.boot.web.servlet.error.ErrorAttributes
9+
import org.springframework.http.MediaType
10+
import org.springframework.stereotype.Component
11+
import org.springframework.web.bind.annotation.RequestMapping
12+
import org.springframework.web.servlet.ModelAndView
13+
import org.springframework.web.servlet.View
14+
import org.springframework.web.servlet.support.ServletUriComponentsBuilder
15+
16+
private val log = KotlinLogging.logger { }
17+
18+
@Component
19+
class ErrorController(errorAttributes: ErrorAttributes) :
20+
BasicErrorController(errorAttributes, ErrorProperties()) {
21+
22+
@RequestMapping(produces = [MediaType.TEXT_HTML_VALUE])
23+
override fun errorHtml(request: HttpServletRequest, response: HttpServletResponse): ModelAndView {
24+
val modelAndView = super.errorHtml(request, response)
25+
26+
response.addHeader("Content-Type", MediaType.TEXT_HTML_VALUE)
27+
28+
val urlPrefix = removeErrorSegmentFromUrl(ServletUriComponentsBuilder.fromCurrentRequest().toUriString())
29+
val url = "$urlPrefix/swagger-ui/index.html"
30+
31+
log.debug { "Generated url $url to Swagger UI in 'not found page'" }
32+
33+
modelAndView.view = NotFoundView(url)
34+
return modelAndView
35+
}
36+
37+
fun removeErrorSegmentFromUrl(url: String): String {
38+
val lastSlashIndex = url.trimEnd('/').lastIndexOf("error")
39+
return url.substring(0, lastSlashIndex).trim('/')
40+
}
41+
}
42+
43+
data class NotFoundView(private val url: String?) : View {
44+
45+
override fun render(model: MutableMap<String, *>?, request: HttpServletRequest, response: HttpServletResponse) {
46+
val html: String = """
47+
<!DOCTYPE html>
48+
<html lang="en">
49+
<head>
50+
<meta charset="UTF-8">
51+
<title>Error 404</title>
52+
</head>
53+
<body>
54+
<h1>LAPIS</h1>
55+
<h3>Page not found!</h3>
56+
<a href="$url">Visit our swagger-ui</a>
57+
</body>
58+
</html>
59+
""".trimIndent()
60+
61+
response.outputStream.write(html.toByteArray())
62+
}
63+
}

lapis2/src/main/resources/public/error/404.html

Lines changed: 0 additions & 12 deletions
This file was deleted.

siloLapisTests/test/unknownUrl.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ describe('Error handling: UnknownUrl', () => {
1818

1919
let responseBody = await result.text();
2020
expect(responseBody).contains('Page not found');
21-
expect(responseBody).contains('a href="/swagger-ui/index.html"');
21+
expect(responseBody).contains('<a href="http://localhost:8080/swagger-ui/index.html">');
2222
});
2323
});

0 commit comments

Comments
 (0)