package api import ( "encoding/json" "fmt" "io" "net/http" "net/http/httptest" "net/url" "testing" "time" "git.frostfs.info/TrueCloudLab/frostfs-s3-gw/metrics" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" "github.com/stretchr/testify/require" "go.uber.org/zap/zaptest" ) func TestRouterUploadPart(t *testing.T) { chiRouter := prepareRouter(t) w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodPut, "/dkirillov/fix-object", nil) query := make(url.Values) query.Set("uploadId", "some-id") query.Set("partNumber", "1") r.URL.RawQuery = query.Encode() chiRouter.ServeHTTP(w, r) resp := readResponse(t, w) require.Equal(t, "UploadPart", resp.Method) } func TestRouterListMultipartUploads(t *testing.T) { chiRouter := prepareRouter(t) w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodGet, "/test-bucket", nil) query := make(url.Values) query.Set("uploads", "") r.URL.RawQuery = query.Encode() chiRouter.ServeHTTP(w, r) resp := readResponse(t, w) require.Equal(t, "ListMultipartUploads", resp.Method) } func TestRouterObjectWithSlashes(t *testing.T) { chiRouter := prepareRouter(t) bktName, objName := "dkirillov", "/fix/object" target := fmt.Sprintf("/%s/%s", bktName, objName) w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodPut, target, nil) chiRouter.ServeHTTP(w, r) resp := readResponse(t, w) require.Equal(t, "PutObject", resp.Method) require.Equal(t, objName, resp.ReqInfo.ObjectName) } func TestRouterObjectEscaping(t *testing.T) { chiRouter := prepareRouter(t) bktName := "dkirillov" for _, tc := range []struct { name string expectedObjName string objName string }{ { name: "simple", expectedObjName: "object", objName: "object", }, { name: "with slashes", expectedObjName: "fix/object", objName: "fix/object", }, { name: "with percentage", expectedObjName: "fix/object%ac", objName: "fix/object%ac", }, { name: "with percentage escaped", expectedObjName: "fix/object%ac", objName: "fix/object%25ac", }, } { t.Run(tc.name, func(t *testing.T) { target := fmt.Sprintf("/%s/%s", bktName, tc.objName) w := httptest.NewRecorder() r := httptest.NewRequest(http.MethodPut, target, nil) chiRouter.ServeHTTP(w, r) resp := readResponse(t, w) require.Equal(t, "PutObject", resp.Method) require.Equal(t, tc.expectedObjName, resp.ReqInfo.ObjectName) }) } } func prepareRouter(t *testing.T) *chi.Mux { throttleOps := middleware.ThrottleOpts{ Limit: 10, BacklogTimeout: 30 * time.Second, } handleMock := &handlerMock{t: t} cntrMock := ¢erMock{} log := zaptest.NewLogger(t) metric := &metrics.AppMetrics{} chiRouter := chi.NewRouter() AttachChi(chiRouter, nil, throttleOps, handleMock, cntrMock, log, metric) return chiRouter } func readResponse(t *testing.T, w *httptest.ResponseRecorder) handlerResult { var res handlerResult resData, err := io.ReadAll(w.Result().Body) require.NoError(t, err) err = json.Unmarshal(resData, &res) require.NoErrorf(t, err, "actual body: '%s'", string(resData)) return res }