LocalAI/core/http/utils/baseurl.go

25 lines
649 B
Go
Raw Normal View History

feat(ui): path prefix support via HTTP header (#4497) Makes the web app honour the `X-Forwarded-Prefix` HTTP request header that may be sent by a reverse-proxy in order to inform the app that its public routes contain a path prefix. For instance this allows to serve the webapp via a reverse-proxy/ingress controller under a path prefix/sub path such as e.g. `/localai/` while still being able to use the regular LocalAI routes/paths without prefix when directly connecting to the LocalAI server. Changes: * Add new `StripPathPrefix` middleware to strip the path prefix (provided with the `X-Forwarded-Prefix` HTTP request header) from the request path prior to matching the HTTP route. * Add a `BaseURL` utility function to build the base URL, honouring the `X-Forwarded-Prefix` HTTP request header. * Generate the derived base URL into the HTML (`head.html` template) as `<base/>` tag. * Make all webapp-internal URLs (within HTML+JS) relative in order to make the browser resolve them against the `<base/>` URL specified within each HTML page's header. * Make font URLs within the CSS files relative to the CSS file. * Generate redirect location URLs using the new `BaseURL` function. * Use the new `BaseURL` function to generate absolute URLs within gallery JSON responses. Closes #3095 TL;DR: The header-based approach allows to move the path prefix configuration concern completely to the reverse-proxy/ingress as opposed to having to align the path prefix configuration between LocalAI, the reverse-proxy and potentially other internal LocalAI clients. The gofiber swagger handler already supports path prefixes this way, see https://github.com/gofiber/swagger/blob/e2d9e9916d8809e8b23c4365f8acfbbd8a71c4cd/swagger.go#L79 Signed-off-by: Max Goltzsche <max.goltzsche@gmail.com>
2025-01-07 17:18:21 +01:00
package utils
import (
"strings"
"github.com/gofiber/fiber/v2"
)
// BaseURL returns the base URL for the given HTTP request context.
// It takes into account that the app may be exposed by a reverse-proxy under a different protocol, host and path.
// The returned URL is guaranteed to end with `/`.
// The method should be used in conjunction with the StripPathPrefix middleware.
func BaseURL(c *fiber.Ctx) string {
path := c.Path()
origPath := c.OriginalURL()
if path != origPath && strings.HasSuffix(origPath, path) {
pathPrefix := origPath[:len(origPath)-len(path)+1]
return c.BaseURL() + pathPrefix
}
return c.BaseURL() + "/"
}