mirror of
https://github.com/mudler/LocalAI.git
synced 2025-01-11 07:23:09 +00:00
8cc2d01caa
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>
121 lines
6.5 KiB
HTML
121 lines
6.5 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
{{template "views/partials/head" .}}
|
|
|
|
<body class="bg-gray-900 text-gray-200">
|
|
<div class="flex flex-col min-h-screen">
|
|
|
|
{{template "views/partials/navbar" .}}
|
|
|
|
<div class="container mx-auto px-4 flex-grow">
|
|
<div class="header text-center py-12">
|
|
<h1 class="text-5xl font-bold text-gray-100">Welcome to <i>your</i> LocalAI instance!</h1>
|
|
<p class="mt-4 text-lg">The FOSS alternative to OpenAI, Claude, ...</p>
|
|
<a href="https://localai.io" target="_blank" class="mt-4 inline-block bg-blue-500 text-white py-2 px-4 rounded-lg shadow transition duration-300 ease-in-out hover:bg-blue-700 hover:shadow-lg">
|
|
<i class="fas fa-book-reader pr-2"></i>Documentation
|
|
</a>
|
|
</div>
|
|
|
|
<div class="models mt-4">
|
|
{{template "views/partials/inprogress" .}}
|
|
{{ if eq (len .ModelsConfig) 0 }}
|
|
<h2 class="text-center text-3xl font-semibold text-gray-100"> <i class="text-yellow-200 ml-2 fa-solid fa-triangle-exclamation animate-pulse"></i> Ouch! seems you don't have any models installed from the LocalAI gallery!</h2>
|
|
<p class="text-center mt-4 text-xl">..install something from the <a class="text-gray-400 hover:text-white ml-1 px-3 py-2 rounded" href="browse">🖼️ Gallery</a> or check the <a href="https://localai.io/basics/getting_started/" class="text-gray-400 hover:text-white ml-1 px-3 py-2 rounded"> <i class="fa-solid fa-book"></i> Getting started documentation </a></p>
|
|
|
|
{{ if ne (len .Models) 0 }}
|
|
<hr class="my-4">
|
|
<h3 class="text-center text-xl font-semibold text-gray-100">
|
|
However, It seems you have installed some models installed without a configuration file:
|
|
</h3>
|
|
{{ range .Models }}
|
|
<div class="bg-gray-800 border-b border-gray-700 p-4 mt-4">
|
|
<h4 class="text-md font-bold text-gray-200">{{.}}</h4>
|
|
</div>
|
|
{{end}}
|
|
{{end}}
|
|
{{ else }}
|
|
{{ $modelsN := len .ModelsConfig}}
|
|
{{ $modelsN = add $modelsN (len .Models)}}
|
|
<h2 class="text-center text-3xl font-semibold text-gray-100">{{$modelsN}} Installed model(s)</h2>
|
|
<table class="table-auto mt-4 w-full text-left text-gray-200">
|
|
<thead class="text-xs text-gray-400 uppercase bg-gray-700">
|
|
<tr>
|
|
<th class="px-4 py-2"></th>
|
|
<th class="px-4 py-2">Model Name</th>
|
|
<th class="px-4 py-2">Backend</th>
|
|
<th class="px-4 py-2 float-right">Actions</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{{$galleryConfig:=.GalleryConfig}}
|
|
{{$noicon:="https://upload.wikimedia.org/wikipedia/commons/6/65/No-Image-Placeholder.svg"}}
|
|
{{ range .ModelsConfig }}
|
|
{{ $cfg:= index $galleryConfig .Name}}
|
|
<tr class="bg-gray-800 border-b border-gray-700">
|
|
<td class="px-4 py-3">
|
|
{{ with $cfg }}
|
|
<img {{ if $cfg.Icon }}
|
|
src="{{$cfg.Icon}}"
|
|
{{ else }}
|
|
src="{{$noicon}}"
|
|
{{ end }}
|
|
class="rounded-t-lg max-h-24 max-w-24 object-cover mt-3"
|
|
>
|
|
{{ else}}
|
|
<img src="{{$noicon}}" class="rounded-t-lg max-h-24 max-w-24 object-cover mt-3">
|
|
{{ end }}
|
|
</td>
|
|
<td class="px-4 py-3 font-bold">
|
|
<p class="font-bold text-white flex items-center"><i class="fas fa-brain pr-2"></i><a href="browse?term={{.Name}}">{{.Name}}</a></p>
|
|
</td>
|
|
<td class="px-4 py-3 font-bold">
|
|
{{ if .Backend }}
|
|
<!-- Badge for Backend -->
|
|
<span class="inline-block bg-blue-500 text-white py-1 px-3 rounded-full text-xs">
|
|
{{.Backend}}
|
|
</span>
|
|
{{ else }}
|
|
<span class="inline-block bg-yellow-500 text-white py-1 px-3 rounded-full text-xs">
|
|
auto
|
|
</span>
|
|
{{ end }}
|
|
</td>
|
|
|
|
<td class="px-4 py-3">
|
|
<button
|
|
class="float-right inline-block rounded bg-red-800 px-6 pb-2.5 mb-3 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-primary-3 transition duration-150 ease-in-out hover:bg-red-accent-300 hover:shadow-red-2 focus:bg-red-accent-300 focus:shadow-primary-2 focus:outline-none focus:ring-0 active:bg-red-600 active:shadow-primary-2 dark:shadow-black/30 dark:hover:shadow-dark-strong dark:focus:shadow-dark-strong dark:active:shadow-dark-strong"
|
|
data-twe-ripple-color="light" data-twe-ripple-init="" hx-confirm="Are you sure you wish to delete the model?" hx-post="browse/delete/model/{{.Name}}" hx-swap="outerHTML"><i class="fa-solid fa-cancel pr-2"></i>Delete</button>
|
|
</td>
|
|
{{ end }}
|
|
{{ range .Models }}
|
|
<tr class="bg-gray-800 border-b border-gray-700">
|
|
<td class="px-4 py-3">
|
|
<img src="{{$noicon}}" class="rounded-t-lg max-h-24 max-w-24 object-cover mt-3">
|
|
</td>
|
|
<td class="px-4 py-3 font-bold">
|
|
<p class="font-bold text-white flex items-center"><i class="fas fa-brain pr-2"></i>{{.}}</p>
|
|
</td>
|
|
<td class="px-4 py-3 font-bold">
|
|
<span class="inline-block bg-yellow-500 text-white py-1 px-3 rounded-full text-xs">
|
|
auto
|
|
</span>
|
|
</td>
|
|
|
|
<td class="px-4 py-3">
|
|
<span class="float-right inline-block bg-red-800 text-white py-1 px-3 rounded-full text-xs">
|
|
No Configuration
|
|
</span>
|
|
</td>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
{{ end }}
|
|
</div>
|
|
</div>
|
|
|
|
{{template "views/partials/footer" .}}
|
|
</div>
|
|
|
|
</body>
|
|
</html>
|