package httpapi_test import ( "encoding/json" "net/http" "net/http/httptest" "testing" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/wangjia/pangolin/server/api/gen" "github.com/wangjia/pangolin/server/internal/httpapi" ) func newTestServer() http.Handler { r := chi.NewRouter() r.Use(middleware.Recoverer) gen.HandlerFromMuxWithBaseURL(&httpapi.UnimplementedServer{}, r, "/v1") return r } type errorBody struct { Code string `json:"code"` MessageZH string `json:"message_zh"` MessageEn string `json:"message_en"` } func Test501StructuredBody(t *testing.T) { srv := newTestServer() // All defined /v1 routes should return 501 with the structured body. routes := []struct { method string path string }{ {"GET", "/v1/plans"}, {"GET", "/v1/nodes"}, {"GET", "/v1/me"}, {"GET", "/v1/me/devices"}, {"GET", "/v1/usage"}, {"GET", "/v1/notices"}, {"POST", "/v1/auth/code"}, {"POST", "/v1/auth/register"}, {"POST", "/v1/auth/login"}, {"POST", "/v1/auth/refresh"}, {"POST", "/v1/redeem"}, {"POST", "/v1/ads/unlock"}, {"DELETE", "/v1/me/devices/00000000-0000-0000-0000-000000000001"}, {"POST", "/v1/nodes/00000000-0000-0000-0000-000000000001/connect"}, {"POST", "/v1/nodes/00000000-0000-0000-0000-000000000001/disconnect"}, } for _, tc := range routes { t.Run(tc.method+" "+tc.path, func(t *testing.T) { req := httptest.NewRequest(tc.method, tc.path, nil) rec := httptest.NewRecorder() srv.ServeHTTP(rec, req) if rec.Code != http.StatusNotImplemented { t.Errorf("expected 501, got %d", rec.Code) } var body errorBody if err := json.NewDecoder(rec.Body).Decode(&body); err != nil { t.Fatalf("could not decode body: %v", err) } if body.Code != "NOT_IMPLEMENTED" { t.Errorf("code: want NOT_IMPLEMENTED, got %q", body.Code) } if body.MessageZH == "" { t.Error("message_zh is empty") } if body.MessageEn == "" { t.Error("message_en is empty") } }) } } func Test404ForUndefinedRoutes(t *testing.T) { srv := newTestServer() paths := []string{ "/v1/nonexistent", "/v2/plans", "/totally/wrong", } for _, p := range paths { t.Run(p, func(t *testing.T) { req := httptest.NewRequest("GET", p, nil) rec := httptest.NewRecorder() srv.ServeHTTP(rec, req) if rec.Code != http.StatusNotFound { t.Errorf("path %s: expected 404, got %d", p, rec.Code) } }) } } func TestHealthzNotAffected(t *testing.T) { r := chi.NewRouter() r.Get("/healthz", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte(`{"status":"ok"}`)) }) gen.HandlerFromMuxWithBaseURL(&httpapi.UnimplementedServer{}, r, "/v1") req := httptest.NewRequest("GET", "/healthz", nil) rec := httptest.NewRecorder() r.ServeHTTP(rec, req) if rec.Code != http.StatusOK { t.Errorf("healthz: expected 200, got %d", rec.Code) } }