mirror of
https://github.com/lordmathis/llamactl.git
synced 2025-11-06 00:54:23 +00:00
Implement helper response handling functions
This commit is contained in:
@@ -6,6 +6,7 @@ import (
|
|||||||
"llamactl/pkg/config"
|
"llamactl/pkg/config"
|
||||||
"llamactl/pkg/instance"
|
"llamactl/pkg/instance"
|
||||||
"llamactl/pkg/manager"
|
"llamactl/pkg/manager"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -18,7 +19,25 @@ type errorResponse struct {
|
|||||||
func writeError(w http.ResponseWriter, status int, code, details string) {
|
func writeError(w http.ResponseWriter, status int, code, details string) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.WriteHeader(status)
|
w.WriteHeader(status)
|
||||||
_ = json.NewEncoder(w).Encode(errorResponse{Error: code, Details: details})
|
if err := json.NewEncoder(w).Encode(errorResponse{Error: code, Details: details}); err != nil {
|
||||||
|
log.Printf("Failed to encode error response: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeJSON(w http.ResponseWriter, status int, data any) {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(status)
|
||||||
|
if err := json.NewEncoder(w).Encode(data); err != nil {
|
||||||
|
log.Printf("Failed to encode JSON response: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeText(w http.ResponseWriter, status int, data string) {
|
||||||
|
w.Header().Set("Content-Type", "text/plain")
|
||||||
|
w.WriteHeader(status)
|
||||||
|
if _, err := w.Write([]byte(data)); err != nil {
|
||||||
|
log.Printf("Failed to write text response: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Handler struct {
|
type Handler struct {
|
||||||
|
|||||||
@@ -27,39 +27,39 @@ func (h *Handler) LlamaCppProxy(onDemandStart bool) http.HandlerFunc {
|
|||||||
// Validate instance name at the entry point
|
// Validate instance name at the entry point
|
||||||
validatedName, err := validation.ValidateInstanceName(name)
|
validatedName, err := validation.ValidateInstanceName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Invalid instance name: "+err.Error(), http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_instance_name", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Route to the appropriate inst based on instance name
|
// Route to the appropriate inst based on instance name
|
||||||
inst, err := h.InstanceManager.GetInstance(validatedName)
|
inst, err := h.InstanceManager.GetInstance(validatedName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Invalid instance: "+err.Error(), http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_instance", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
options := inst.GetOptions()
|
options := inst.GetOptions()
|
||||||
if options == nil {
|
if options == nil {
|
||||||
http.Error(w, "Cannot obtain Instance's options", http.StatusInternalServerError)
|
writeError(w, http.StatusInternalServerError, "options_failed", "Cannot obtain Instance's options")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if options.BackendOptions.BackendType != backends.BackendTypeLlamaCpp {
|
if options.BackendOptions.BackendType != backends.BackendTypeLlamaCpp {
|
||||||
http.Error(w, "Instance is not a llama.cpp server.", http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_backend", "Instance is not a llama.cpp server.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !inst.IsRemote() && !inst.IsRunning() && onDemandStart {
|
if !inst.IsRemote() && !inst.IsRunning() && onDemandStart {
|
||||||
err := h.ensureInstanceRunning(inst)
|
err := h.ensureInstanceRunning(inst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to ensure instance is running: "+err.Error(), http.StatusInternalServerError)
|
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 {
|
||||||
http.Error(w, "Failed to get proxy: "+err.Error(), http.StatusInternalServerError)
|
writeError(w, http.StatusInternalServerError, "proxy_failed", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,10 +124,7 @@ func (h *Handler) ParseLlamaCommand() http.HandlerFunc {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
writeJSON(w, http.StatusOK, options)
|
||||||
if err := json.NewEncoder(w).Encode(options); err != nil {
|
|
||||||
writeError(w, http.StatusInternalServerError, "encode_error", err.Error())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,10 +153,7 @@ func (h *Handler) ParseMlxCommand() http.HandlerFunc {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
writeJSON(w, http.StatusOK, options)
|
||||||
if err := json.NewEncoder(w).Encode(options); err != nil {
|
|
||||||
writeError(w, http.StatusInternalServerError, "encode_error", err.Error())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,10 +182,7 @@ func (h *Handler) ParseVllmCommand() http.HandlerFunc {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
writeJSON(w, http.StatusOK, options)
|
||||||
if err := json.NewEncoder(w).Encode(options); err != nil {
|
|
||||||
writeError(w, http.StatusInternalServerError, "encode_error", err.Error())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,11 +200,10 @@ func (h *Handler) LlamaServerHelpHandler() http.HandlerFunc {
|
|||||||
helpCmd := exec.Command("llama-server", "--help")
|
helpCmd := exec.Command("llama-server", "--help")
|
||||||
output, err := helpCmd.CombinedOutput()
|
output, err := helpCmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to get help: "+err.Error(), http.StatusInternalServerError)
|
writeError(w, http.StatusInternalServerError, "command_failed", "Failed to get help: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "text/plain")
|
writeText(w, http.StatusOK, string(output))
|
||||||
w.Write(output)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,11 +221,10 @@ func (h *Handler) LlamaServerVersionHandler() http.HandlerFunc {
|
|||||||
versionCmd := exec.Command("llama-server", "--version")
|
versionCmd := exec.Command("llama-server", "--version")
|
||||||
output, err := versionCmd.CombinedOutput()
|
output, err := versionCmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to get version: "+err.Error(), http.StatusInternalServerError)
|
writeError(w, http.StatusInternalServerError, "command_failed", "Failed to get version: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "text/plain")
|
writeText(w, http.StatusOK, string(output))
|
||||||
w.Write(output)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,10 +242,9 @@ func (h *Handler) LlamaServerListDevicesHandler() http.HandlerFunc {
|
|||||||
listCmd := exec.Command("llama-server", "--list-devices")
|
listCmd := exec.Command("llama-server", "--list-devices")
|
||||||
output, err := listCmd.CombinedOutput()
|
output, err := listCmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to list devices: "+err.Error(), http.StatusInternalServerError)
|
writeError(w, http.StatusInternalServerError, "command_failed", "Failed to list devices: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Type", "text/plain")
|
writeText(w, http.StatusOK, string(output))
|
||||||
w.Write(output)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,15 +26,11 @@ func (h *Handler) ListInstances() http.HandlerFunc {
|
|||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
instances, err := h.InstanceManager.ListInstances()
|
instances, err := h.InstanceManager.ListInstances()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to list instances: "+err.Error(), http.StatusInternalServerError)
|
writeError(w, http.StatusInternalServerError, "list_failed", "Failed to list instances: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
writeJSON(w, http.StatusOK, instances)
|
||||||
if err := json.NewEncoder(w).Encode(instances); err != nil {
|
|
||||||
http.Error(w, "Failed to encode instances: "+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,28 +53,23 @@ func (h *Handler) CreateInstance() http.HandlerFunc {
|
|||||||
|
|
||||||
validatedName, err := validation.ValidateInstanceName(name)
|
validatedName, err := validation.ValidateInstanceName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Invalid instance name: "+err.Error(), http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_instance_name", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var options instance.Options
|
var options instance.Options
|
||||||
if err := json.NewDecoder(r.Body).Decode(&options); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&options); err != nil {
|
||||||
http.Error(w, "Invalid request body", http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_request", "Invalid request body")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
inst, err := h.InstanceManager.CreateInstance(validatedName, &options)
|
inst, err := h.InstanceManager.CreateInstance(validatedName, &options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to create instance: "+err.Error(), http.StatusInternalServerError)
|
writeError(w, http.StatusInternalServerError, "create_failed", "Failed to create instance: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
writeJSON(w, http.StatusCreated, inst)
|
||||||
w.WriteHeader(http.StatusCreated)
|
|
||||||
if err := json.NewEncoder(w).Encode(inst); err != nil {
|
|
||||||
http.Error(w, "Failed to encode instance: "+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,21 +90,17 @@ func (h *Handler) GetInstance() http.HandlerFunc {
|
|||||||
|
|
||||||
validatedName, err := validation.ValidateInstanceName(name)
|
validatedName, err := validation.ValidateInstanceName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Invalid instance name: "+err.Error(), http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_instance_name", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
inst, err := h.InstanceManager.GetInstance(validatedName)
|
inst, err := h.InstanceManager.GetInstance(validatedName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Invalid instance: "+err.Error(), http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_instance", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
writeJSON(w, http.StatusOK, inst)
|
||||||
if err := json.NewEncoder(w).Encode(inst); err != nil {
|
|
||||||
http.Error(w, "Failed to encode instance: "+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,27 +123,23 @@ func (h *Handler) UpdateInstance() http.HandlerFunc {
|
|||||||
|
|
||||||
validatedName, err := validation.ValidateInstanceName(name)
|
validatedName, err := validation.ValidateInstanceName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Invalid instance name: "+err.Error(), http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_instance_name", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var options instance.Options
|
var options instance.Options
|
||||||
if err := json.NewDecoder(r.Body).Decode(&options); err != nil {
|
if err := json.NewDecoder(r.Body).Decode(&options); err != nil {
|
||||||
http.Error(w, "Invalid request body", http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_request", "Invalid request body")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
inst, err := h.InstanceManager.UpdateInstance(validatedName, &options)
|
inst, err := h.InstanceManager.UpdateInstance(validatedName, &options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to update instance: "+err.Error(), http.StatusInternalServerError)
|
writeError(w, http.StatusInternalServerError, "update_failed", "Failed to update instance: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
writeJSON(w, http.StatusOK, inst)
|
||||||
if err := json.NewEncoder(w).Encode(inst); err != nil {
|
|
||||||
http.Error(w, "Failed to encode instance: "+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,7 +160,7 @@ func (h *Handler) StartInstance() http.HandlerFunc {
|
|||||||
|
|
||||||
validatedName, err := validation.ValidateInstanceName(name)
|
validatedName, err := validation.ValidateInstanceName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Invalid instance name: "+err.Error(), http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_instance_name", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,19 +168,15 @@ func (h *Handler) StartInstance() http.HandlerFunc {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
// Check if error is due to maximum running instances limit
|
// Check if error is due to maximum running instances limit
|
||||||
if _, ok := err.(manager.MaxRunningInstancesError); ok {
|
if _, ok := err.(manager.MaxRunningInstancesError); ok {
|
||||||
http.Error(w, err.Error(), http.StatusConflict)
|
writeError(w, http.StatusConflict, "max_instances_reached", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
http.Error(w, "Failed to start instance: "+err.Error(), http.StatusInternalServerError)
|
writeError(w, http.StatusInternalServerError, "start_failed", "Failed to start instance: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
writeJSON(w, http.StatusOK, inst)
|
||||||
if err := json.NewEncoder(w).Encode(inst); err != nil {
|
|
||||||
http.Error(w, "Failed to encode instance: "+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,21 +197,17 @@ func (h *Handler) StopInstance() http.HandlerFunc {
|
|||||||
|
|
||||||
validatedName, err := validation.ValidateInstanceName(name)
|
validatedName, err := validation.ValidateInstanceName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Invalid instance name: "+err.Error(), http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_instance_name", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
inst, err := h.InstanceManager.StopInstance(validatedName)
|
inst, err := h.InstanceManager.StopInstance(validatedName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to stop instance: "+err.Error(), http.StatusInternalServerError)
|
writeError(w, http.StatusInternalServerError, "stop_failed", "Failed to stop instance: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
writeJSON(w, http.StatusOK, inst)
|
||||||
if err := json.NewEncoder(w).Encode(inst); err != nil {
|
|
||||||
http.Error(w, "Failed to encode instance: "+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,21 +228,17 @@ func (h *Handler) RestartInstance() http.HandlerFunc {
|
|||||||
|
|
||||||
validatedName, err := validation.ValidateInstanceName(name)
|
validatedName, err := validation.ValidateInstanceName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Invalid instance name: "+err.Error(), http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_instance_name", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
inst, err := h.InstanceManager.RestartInstance(validatedName)
|
inst, err := h.InstanceManager.RestartInstance(validatedName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to restart instance: "+err.Error(), http.StatusInternalServerError)
|
writeError(w, http.StatusInternalServerError, "restart_failed", "Failed to restart instance: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
writeJSON(w, http.StatusOK, inst)
|
||||||
if err := json.NewEncoder(w).Encode(inst); err != nil {
|
|
||||||
http.Error(w, "Failed to encode instance: "+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,12 +258,12 @@ func (h *Handler) DeleteInstance() http.HandlerFunc {
|
|||||||
|
|
||||||
validatedName, err := validation.ValidateInstanceName(name)
|
validatedName, err := validation.ValidateInstanceName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Invalid instance name: "+err.Error(), http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_instance_name", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.InstanceManager.DeleteInstance(validatedName); err != nil {
|
if err := h.InstanceManager.DeleteInstance(validatedName); err != nil {
|
||||||
http.Error(w, "Failed to delete instance: "+err.Error(), http.StatusInternalServerError)
|
writeError(w, http.StatusInternalServerError, "delete_failed", "Failed to delete instance: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,7 +289,7 @@ func (h *Handler) GetInstanceLogs() http.HandlerFunc {
|
|||||||
|
|
||||||
validatedName, err := validation.ValidateInstanceName(name)
|
validatedName, err := validation.ValidateInstanceName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Invalid instance name: "+err.Error(), http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_instance_name", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,7 +298,7 @@ func (h *Handler) GetInstanceLogs() http.HandlerFunc {
|
|||||||
if lines != "" {
|
if lines != "" {
|
||||||
parsedLines, err := strconv.Atoi(lines)
|
parsedLines, err := strconv.Atoi(lines)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Invalid lines parameter: "+err.Error(), http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_parameter", "Invalid lines parameter: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
numLines = parsedLines
|
numLines = parsedLines
|
||||||
@@ -336,12 +307,11 @@ func (h *Handler) GetInstanceLogs() http.HandlerFunc {
|
|||||||
// Use the instance manager which handles both local and remote instances
|
// Use the instance manager which handles both local and remote instances
|
||||||
logs, err := h.InstanceManager.GetInstanceLogs(validatedName, numLines)
|
logs, err := h.InstanceManager.GetInstanceLogs(validatedName, numLines)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to get logs: "+err.Error(), http.StatusInternalServerError)
|
writeError(w, http.StatusInternalServerError, "logs_failed", "Failed to get logs: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "text/plain")
|
writeText(w, http.StatusOK, logs)
|
||||||
w.Write([]byte(logs))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,25 +333,25 @@ func (h *Handler) ProxyToInstance() http.HandlerFunc {
|
|||||||
|
|
||||||
validatedName, err := validation.ValidateInstanceName(name)
|
validatedName, err := validation.ValidateInstanceName(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Invalid instance name: "+err.Error(), http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_instance_name", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
inst, err := h.InstanceManager.GetInstance(validatedName)
|
inst, err := h.InstanceManager.GetInstance(validatedName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to get instance: "+err.Error(), http.StatusInternalServerError)
|
writeError(w, http.StatusInternalServerError, "instance_failed", "Failed to get instance: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !inst.IsRunning() {
|
if !inst.IsRunning() {
|
||||||
http.Error(w, "Instance is not running", http.StatusServiceUnavailable)
|
writeError(w, http.StatusServiceUnavailable, "instance_not_running", "Instance is not running")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the cached proxy for this instance
|
// Get the cached proxy for this instance
|
||||||
proxy, err := inst.GetProxy()
|
proxy, err := inst.GetProxy()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to get proxy: "+err.Error(), http.StatusInternalServerError)
|
writeError(w, http.StatusInternalServerError, "proxy_failed", "Failed to get proxy: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
@@ -31,11 +30,7 @@ func (h *Handler) ListNodes() http.HandlerFunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
writeJSON(w, http.StatusOK, nodeResponses)
|
||||||
if err := json.NewEncoder(w).Encode(nodeResponses); err != nil {
|
|
||||||
http.Error(w, "Failed to encode nodes: "+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,13 +50,13 @@ func (h *Handler) GetNode() http.HandlerFunc {
|
|||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
name := chi.URLParam(r, "name")
|
name := chi.URLParam(r, "name")
|
||||||
if name == "" {
|
if name == "" {
|
||||||
http.Error(w, "Node name cannot be empty", http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_request", "Node name cannot be empty")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeConfig, exists := h.cfg.Nodes[name]
|
nodeConfig, exists := h.cfg.Nodes[name]
|
||||||
if !exists {
|
if !exists {
|
||||||
http.Error(w, "Node not found", http.StatusNotFound)
|
writeError(w, http.StatusNotFound, "not_found", "Node not found")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,10 +65,6 @@ func (h *Handler) GetNode() http.HandlerFunc {
|
|||||||
Address: nodeConfig.Address,
|
Address: nodeConfig.Address,
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
writeJSON(w, http.StatusOK, nodeResponse)
|
||||||
if err := json.NewEncoder(w).Encode(nodeResponse); err != nil {
|
|
||||||
http.Error(w, "Failed to encode node: "+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ func (h *Handler) OpenAIListInstances() http.HandlerFunc {
|
|||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
instances, err := h.InstanceManager.ListInstances()
|
instances, err := h.InstanceManager.ListInstances()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to list instances: "+err.Error(), http.StatusInternalServerError)
|
writeError(w, http.StatusInternalServerError, "list_failed", "Failed to list instances: "+err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,11 +54,7 @@ func (h *Handler) OpenAIListInstances() http.HandlerFunc {
|
|||||||
Data: openaiInstances,
|
Data: openaiInstances,
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
writeJSON(w, http.StatusOK, openaiResponse)
|
||||||
if err := json.NewEncoder(w).Encode(openaiResponse); err != nil {
|
|
||||||
http.Error(w, "Failed to encode instances: "+err.Error(), http.StatusInternalServerError)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +74,7 @@ func (h *Handler) OpenAIProxy() http.HandlerFunc {
|
|||||||
// Read the entire body first
|
// Read the entire body first
|
||||||
bodyBytes, err := io.ReadAll(r.Body)
|
bodyBytes, err := io.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to read request body", http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_request", "Failed to read request body")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
r.Body.Close()
|
r.Body.Close()
|
||||||
@@ -86,41 +82,41 @@ func (h *Handler) OpenAIProxy() http.HandlerFunc {
|
|||||||
// Parse the body to extract instance name
|
// Parse the body to extract instance name
|
||||||
var requestBody map[string]any
|
var requestBody map[string]any
|
||||||
if err := json.Unmarshal(bodyBytes, &requestBody); err != nil {
|
if err := json.Unmarshal(bodyBytes, &requestBody); err != nil {
|
||||||
http.Error(w, "Invalid request body", http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_request", "Invalid request body")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
modelName, ok := requestBody["model"].(string)
|
modelName, ok := requestBody["model"].(string)
|
||||||
if !ok || modelName == "" {
|
if !ok || modelName == "" {
|
||||||
http.Error(w, "Instance name is required", http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_request", "Instance name is required")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate instance name at the entry point
|
// Validate instance name at the entry point
|
||||||
validatedName, err := validation.ValidateInstanceName(modelName)
|
validatedName, err := validation.ValidateInstanceName(modelName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Invalid instance name: "+err.Error(), http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_instance_name", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Route to the appropriate inst based on instance name
|
// Route to the appropriate inst based on instance name
|
||||||
inst, err := h.InstanceManager.GetInstance(validatedName)
|
inst, err := h.InstanceManager.GetInstance(validatedName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Invalid instance: "+err.Error(), http.StatusBadRequest)
|
writeError(w, http.StatusBadRequest, "invalid_instance", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !inst.IsRemote() && !inst.IsRunning() {
|
if !inst.IsRemote() && !inst.IsRunning() {
|
||||||
err := h.ensureInstanceRunning(inst)
|
err := h.ensureInstanceRunning(inst)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
http.Error(w, "Failed to ensure instance is running: "+err.Error(), http.StatusInternalServerError)
|
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 {
|
||||||
http.Error(w, "Failed to get proxy: "+err.Error(), http.StatusInternalServerError)
|
writeError(w, http.StatusInternalServerError, "proxy_failed", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
// @Router /version [get]
|
// @Router /version [get]
|
||||||
func (h *Handler) VersionHandler() http.HandlerFunc {
|
func (h *Handler) VersionHandler() http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "text/plain")
|
versionInfo := fmt.Sprintf("Version: %s\nCommit: %s\nBuild Time: %s\n", h.cfg.Version, h.cfg.CommitHash, h.cfg.BuildTime)
|
||||||
fmt.Fprintf(w, "Version: %s\nCommit: %s\nBuild Time: %s\n", h.cfg.Version, h.cfg.CommitHash, h.cfg.BuildTime)
|
writeText(w, http.StatusOK, versionInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user