diff --git a/server/routes.go b/server/routes.go index d9e4fb66b..c493db3fa 100644 --- a/server/routes.go +++ b/server/routes.go @@ -1180,11 +1180,12 @@ func (s *Server) GenerateRoutes() http.Handler { }) r.Handle(method, "/api/tags", s.ListHandler) - r.Handle(method, "/api/version", func(c *gin.Context) { - c.JSON(http.StatusOK, gin.H{"version": version.Version}) - }) } + // Use r.Any to call regular http.Handler handlers + // as we transition to a standard http.ServeMux. + r.Any("/api/version", gin.WrapF(s.versionHandler)) + return r } @@ -1566,6 +1567,24 @@ func (s *Server) ChatHandler(c *gin.Context) { streamResponse(c, ch) } +func (s *Server) versionHandler(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodGet { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) + return + } + + data := struct { + Version string `json:"version"` + }{ + Version: version.Version, + } + + w.Header().Set("Content-Type", "application/json") + if err := json.NewEncoder(w).Encode(data); err != nil { + http.Error(w, "Failed to encode version", http.StatusInternalServerError) + } +} + func handleScheduleError(c *gin.Context, name string, err error) { switch { case errors.Is(err, errCapabilities), errors.Is(err, errRequired): diff --git a/server/routes_test.go b/server/routes_test.go index 1daf36f1a..ad26ca171 100644 --- a/server/routes_test.go +++ b/server/routes_test.go @@ -102,27 +102,6 @@ func Test_Routes(t *testing.T) { } testCases := []testCase{ - { - Name: "Version Handler", - Method: http.MethodGet, - Path: "/api/version", - Setup: func(t *testing.T, req *http.Request) { - }, - Expected: func(t *testing.T, resp *http.Response) { - contentType := resp.Header.Get("Content-Type") - if contentType != "application/json; charset=utf-8" { - t.Errorf("expected content type application/json; charset=utf-8, got %s", contentType) - } - body, err := io.ReadAll(resp.Body) - if err != nil { - t.Fatalf("failed to read response body: %v", err) - } - expectedBody := fmt.Sprintf(`{"version":"%s"}`, version.Version) - if string(body) != expectedBody { - t.Errorf("expected body %s, got %s", expectedBody, string(body)) - } - }, - }, { Name: "Tags Handler (no tags)", Method: http.MethodGet, @@ -673,3 +652,38 @@ func TestNormalize(t *testing.T) { }) } } + +func TestVersionHandler(t *testing.T) { + w := httptest.NewRecorder() + req, _ := http.NewRequest(http.MethodGet, "/api/version", nil) + s := &Server{} + s.versionHandler(w, req) + + if w.Code != http.StatusOK { + t.Fatalf("Expected status code %d, but got %d", http.StatusOK, w.Code) + } + + ct := w.Header().Get("Content-Type") + if ct != "application/json" { + t.Fatalf("Expected content type application/json, but got %s", ct) + } + + var resp struct { + Version string `json:"version"` + } + if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { + t.Fatal(err) + } + + if resp.Version != version.Version { + t.Fatalf("want version %s, got %s", version.Version, resp.Version) + } + + w = httptest.NewRecorder() + req, _ = http.NewRequest(http.MethodPost, "/api/version", nil) + s.versionHandler(w, req) + + if w.Code != http.StatusMethodNotAllowed { + t.Fatalf("Expected status code %d, but got %d", http.StatusMethodNotAllowed, w.Code) + } +}