mirror of
https://github.com/mudler/LocalAI.git
synced 2025-02-11 05:11:14 +00:00
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 e2d9e9916d/swagger.go (L79)
Signed-off-by: Max Goltzsche <max.goltzsche@gmail.com>
55 lines
1.8 KiB
Go
55 lines
1.8 KiB
Go
package localai
|
|
|
|
import (
|
|
"github.com/gofiber/fiber/v2"
|
|
"github.com/mudler/LocalAI/core/config"
|
|
"github.com/mudler/LocalAI/core/gallery"
|
|
"github.com/mudler/LocalAI/core/http/utils"
|
|
"github.com/mudler/LocalAI/core/p2p"
|
|
"github.com/mudler/LocalAI/core/services"
|
|
"github.com/mudler/LocalAI/internal"
|
|
"github.com/mudler/LocalAI/pkg/model"
|
|
)
|
|
|
|
func WelcomeEndpoint(appConfig *config.ApplicationConfig,
|
|
cl *config.BackendConfigLoader, ml *model.ModelLoader, modelStatus func() (map[string]string, map[string]string)) func(*fiber.Ctx) error {
|
|
return func(c *fiber.Ctx) error {
|
|
backendConfigs := cl.GetAllBackendConfigs()
|
|
galleryConfigs := map[string]*gallery.Config{}
|
|
|
|
for _, m := range backendConfigs {
|
|
cfg, err := gallery.GetLocalModelConfiguration(ml.ModelPath, m.Name)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
galleryConfigs[m.Name] = cfg
|
|
}
|
|
|
|
modelsWithoutConfig, _ := services.ListModels(cl, ml, config.NoFilterFn, services.LOOSE_ONLY)
|
|
|
|
// Get model statuses to display in the UI the operation in progress
|
|
processingModels, taskTypes := modelStatus()
|
|
|
|
summary := fiber.Map{
|
|
"Title": "LocalAI API - " + internal.PrintableVersion(),
|
|
"Version": internal.PrintableVersion(),
|
|
"BaseURL": utils.BaseURL(c),
|
|
"Models": modelsWithoutConfig,
|
|
"ModelsConfig": backendConfigs,
|
|
"GalleryConfig": galleryConfigs,
|
|
"IsP2PEnabled": p2p.IsP2PEnabled(),
|
|
"ApplicationConfig": appConfig,
|
|
"ProcessingModels": processingModels,
|
|
"TaskTypes": taskTypes,
|
|
}
|
|
|
|
if string(c.Context().Request.Header.ContentType()) == "application/json" || len(c.Accepts("html")) == 0 {
|
|
// The client expects a JSON response
|
|
return c.Status(fiber.StatusOK).JSON(summary)
|
|
} else {
|
|
// Render index
|
|
return c.Render("views/index", summary)
|
|
}
|
|
}
|
|
}
|