Split LlamaCppProxy handler

This commit is contained in:
2025-10-26 10:21:40 +01:00
parent 9259763054
commit a7593e9a58
2 changed files with 77 additions and 16 deletions

View File

@@ -15,44 +15,105 @@ type ParseCommandRequest struct {
Command string `json:"command"` Command string `json:"command"`
} }
func (h *Handler) LlamaCppProxy(onDemandStart bool) http.HandlerFunc { func (h *Handler) validateLlamaCppInstance(r *http.Request) (*instance.Instance, error) {
inst, err := h.getInstance(r)
if err != nil {
return nil, fmt.Errorf("invalid instance: %w", err)
}
options := inst.GetOptions()
if options == nil {
return nil, fmt.Errorf("cannot obtain instance's options")
}
if options.BackendOptions.BackendType != backends.BackendTypeLlamaCpp {
return nil, fmt.Errorf("instance is not a llama.cpp server")
}
return inst, nil
}
func (h *Handler) stripLlamaCppPrefix(r *http.Request, instName string) {
// Strip the "/llama-cpp/<name>" prefix from the request URL
prefix := fmt.Sprintf("/llama-cpp/%s", instName)
r.URL.Path = strings.TrimPrefix(r.URL.Path, prefix)
}
// LlamaCppUIProxy godoc
// @Summary Proxy requests to llama.cpp UI for the instance
// @Description Proxies requests to the llama.cpp UI for the specified instance
// @Tags backends
// @Security ApiKeyAuth
// @Produce html
// @Param name query string true "Instance Name"
// @Success 200 {string} string "Proxied HTML response"
// @Failure 400 {string} string "Invalid instance"
// @Failure 500 {string} string "Internal Server Error"
// @Router /llama-cpp/{name}/ [get]
func (h *Handler) LlamaCppUIProxy() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
inst, err := h.getInstance(r) inst, err := h.validateLlamaCppInstance(r)
if err != nil { if err != nil {
writeError(w, http.StatusBadRequest, "invalid_instance", err.Error()) writeError(w, http.StatusBadRequest, "invalid instance", err.Error())
return return
} }
options := inst.GetOptions() if !inst.IsRemote() && !inst.IsRunning() {
if options == nil { writeError(w, http.StatusBadRequest, "instance is not running", "Instance is not running")
writeError(w, http.StatusInternalServerError, "options_failed", "Cannot obtain Instance's options")
return return
} }
if options.BackendOptions.BackendType != backends.BackendTypeLlamaCpp { proxy, err := inst.GetProxy()
writeError(w, http.StatusBadRequest, "invalid_backend", "Instance is not a llama.cpp server.") if err != nil {
writeError(w, http.StatusInternalServerError, "failed to get proxy", err.Error())
return return
} }
if !inst.IsRemote() && !inst.IsRunning() && onDemandStart { if !inst.IsRemote() {
h.stripLlamaCppPrefix(r, inst.Name)
}
proxy.ServeHTTP(w, r)
}
}
// LlamaCppProxy godoc
// @Summary Proxy requests to llama.cpp server instance
// @Description Proxies requests to the specified llama.cpp server instance, starting it on-demand if configured
// @Tags backends
// @Security ApiKeyAuth
// @Produce json
// @Param name query string true "Instance Name"
// @Success 200 {object} map[string]any "Proxied response"
// @Failure 400 {string} string "Invalid instance"
// @Failure 500 {string} string "Internal Server Error"
// @Router /llama-cpp/{name}/* [post]
func (h *Handler) LlamaCppProxy() http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
inst, err := h.validateLlamaCppInstance(r)
if err != nil {
writeError(w, http.StatusBadRequest, "invalid instance", err.Error())
return
}
if !inst.IsRemote() && !inst.IsRunning() {
err := h.ensureInstanceRunning(inst) err := h.ensureInstanceRunning(inst)
if err != nil { if err != nil {
writeError(w, http.StatusInternalServerError, "instance_start_failed", err.Error()) writeError(w, http.StatusInternalServerError, "instance start failed", err.Error())
return return
} }
} }
proxy, err := inst.GetProxy() proxy, err := inst.GetProxy()
if err != nil { if err != nil {
writeError(w, http.StatusInternalServerError, "proxy_failed", err.Error()) writeError(w, http.StatusInternalServerError, "failed to get proxy", err.Error())
return return
} }
if !inst.IsRemote() { if !inst.IsRemote() {
// Strip the "/llama-cpp/<name>" prefix from the request URL h.stripLlamaCppPrefix(r, inst.Name)
prefix := fmt.Sprintf("/llama-cpp/%s", inst.Name)
r.URL.Path = strings.TrimPrefix(r.URL.Path, prefix)
} }
proxy.ServeHTTP(w, r) proxy.ServeHTTP(w, r)

View File

@@ -117,7 +117,7 @@ func SetupRouter(handler *Handler) *chi.Mux {
// Public Routes // Public Routes
// Allow llama-cpp server to serve its own WebUI if it is running. // Allow llama-cpp server to serve its own WebUI if it is running.
// Don't auto start the server since it can be accessed without an API key // Don't auto start the server since it can be accessed without an API key
r.Get("/", handler.LlamaCppProxy(false)) r.Get("/", handler.LlamaCppUIProxy())
// Private Routes // Private Routes
r.Group(func(r chi.Router) { r.Group(func(r chi.Router) {
@@ -127,7 +127,7 @@ func SetupRouter(handler *Handler) *chi.Mux {
} }
// This handler auto start the server if it's not running // This handler auto start the server if it's not running
llamaCppHandler := handler.LlamaCppProxy(true) llamaCppHandler := handler.LlamaCppProxy()
// llama.cpp server specific proxy endpoints // llama.cpp server specific proxy endpoints
r.Get("/props", llamaCppHandler) r.Get("/props", llamaCppHandler)