diff --git a/internal/upload/accelerate.go b/internal/upload/accelerate.go index 7c2e635d64d43c060cffc11a9fd05421828959dd..b8e5f6ba443136051e1b692b612e40b731a9b312 100644 --- a/internal/upload/accelerate.go +++ b/internal/upload/accelerate.go @@ -25,13 +25,15 @@ type MultipartClaims struct { jwt.StandardClaims } -func Accelerate(tempDir string, h http.Handler) http.Handler { - // TODO: for Object Store this will need a authorize call - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - localOnlyPreAuth := &api.Response{TempPath: tempDir} +type PreAuthorizer interface { + PreAuthorizeHandler(next api.HandleFunc, suffix string) http.Handler +} + +func Accelerate(rails PreAuthorizer, h http.Handler) http.Handler { + return rails.PreAuthorizeHandler(func(w http.ResponseWriter, r *http.Request, a *api.Response) { s := &savedFileTracker{request: r} - HandleFileUploads(w, r, h, localOnlyPreAuth, s) - }) + HandleFileUploads(w, r, h, a, s) + }, "/authorize") } func (s *savedFileTracker) ProcessFile(_ context.Context, fieldName string, file *filestore.FileHandler, _ *multipart.Writer) error { diff --git a/internal/upload/skip_rails_authorizer.go b/internal/upload/skip_rails_authorizer.go new file mode 100644 index 0000000000000000000000000000000000000000..716467b884174b04ead1ccf1e404f6abf15c5c29 --- /dev/null +++ b/internal/upload/skip_rails_authorizer.go @@ -0,0 +1,22 @@ +package upload + +import ( + "net/http" + + "gitlab.com/gitlab-org/gitlab-workhorse/internal/api" +) + +// SkipRailsAuthorizer implements a fake PreAuthorizer that do not calls rails API and +// authorize each call as a local only upload to TempPath +type SkipRailsAuthorizer struct { + // TempPath is the temporary path for a local only upload + TempPath string +} + +// PreAuthorizeHandler implements PreAuthorizer. It always grant the upload. +// The fake API response contains only TempPath +func (l *SkipRailsAuthorizer) PreAuthorizeHandler(next api.HandleFunc, _ string) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + next(w, r, &api.Response{TempPath: l.TempPath}) + }) +} diff --git a/internal/upstream/routes.go b/internal/upstream/routes.go index 4e5258421b4bf4372c0500a4ae9d22b7c8ffac3c..328418a1d140a22abd49a14fec39b285e430c7b3 100644 --- a/internal/upstream/routes.go +++ b/internal/upstream/routes.go @@ -145,7 +145,8 @@ func (u *Upstream) configureRoutes() { sendurl.SendURL, ) - uploadAccelerateProxy := upload.Accelerate(path.Join(u.DocumentRoot, "uploads/tmp"), proxy) + uploadPath := path.Join(u.DocumentRoot, "uploads/tmp") + uploadAccelerateProxy := upload.Accelerate(&upload.SkipRailsAuthorizer{TempPath: uploadPath}, proxy) ciAPIProxyQueue := queueing.QueueRequests("ci_api_job_requests", uploadAccelerateProxy, u.APILimit, u.APIQueueLimit, u.APIQueueTimeout) ciAPILongPolling := builds.RegisterHandler(ciAPIProxyQueue, redis.WatchKey, u.APICILongPollingDuration) @@ -182,6 +183,9 @@ func (u *Upstream) configureRoutes() { ), ), + // Uploads + route("POST", projectPattern+`uploads\z`, upload.Accelerate(api, proxy)), + // For legacy reasons, user uploads are stored under the document root. // To prevent anybody who knows/guesses the URL of a user-uploaded file // from downloading it we make sure requests to /uploads/ do _not_ pass