From 5ec57a9533a4e5f18f4db778d2df0c8b97494826 Mon Sep 17 00:00:00 2001 From: Klaus Post Date: Mon, 14 Feb 2022 09:19:01 -0800 Subject: [PATCH] Add GetObject gzip option (#14226) Enabled with `mc admin config set alias/ api gzip_objects=on` Standard filtering applies (1K response minimum, not compressed content type, not range request, gzip accepted by client). --- cmd/api-router.go | 2 +- cmd/handler-api.go | 9 +++++++++ cmd/object-handlers.go | 4 ++++ internal/config/api/api.go | 10 ++++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/cmd/api-router.go b/cmd/api-router.go index 19baacbd3..537089e88 100644 --- a/cmd/api-router.go +++ b/cmd/api-router.go @@ -287,7 +287,7 @@ func registerAPIRouter(router *mux.Router) { collectAPIStats("getobjectlegalhold", maxClients(gz(httpTraceAll(api.GetObjectLegalHoldHandler))))).Queries("legal-hold", "") // GetObject - note gzip compression is *not* added due to Range requests. router.Methods(http.MethodGet).Path("/{object:.+}").HandlerFunc( - collectAPIStats("getobject", maxClients(httpTraceHdrs(api.GetObjectHandler)))) + collectAPIStats("getobject", maxClients(gz(httpTraceHdrs(api.GetObjectHandler))))) // CopyObject router.Methods(http.MethodPut).Path("/{object:.+}").HeadersRegexp(xhttp.AmzCopySource, ".*?(\\/|%2F).*?").HandlerFunc( collectAPIStats("copyobject", maxClients(gz(httpTraceAll(api.CopyObjectHandler))))) diff --git a/cmd/handler-api.go b/cmd/handler-api.go index 22b6015be..ac8756b88 100644 --- a/cmd/handler-api.go +++ b/cmd/handler-api.go @@ -50,6 +50,7 @@ type apiConfig struct { staleUploadsCleanupInterval time.Duration deleteCleanupInterval time.Duration disableODirect bool + gzipObjects bool } const cgroupLimitFile = "/sys/fs/cgroup/memory/memory.limit_in_bytes" @@ -152,6 +153,7 @@ func (t *apiConfig) init(cfg api.Config, setDriveCounts []int) { t.staleUploadsCleanupInterval = cfg.StaleUploadsCleanupInterval t.deleteCleanupInterval = cfg.DeleteCleanupInterval t.disableODirect = cfg.DisableODirect + t.gzipObjects = cfg.GzipObjects } func (t *apiConfig) isDisableODirect() bool { @@ -161,6 +163,13 @@ func (t *apiConfig) isDisableODirect() bool { return t.disableODirect } +func (t *apiConfig) shouldGzipObjects() bool { + t.mu.RLock() + defer t.mu.RUnlock() + + return t.gzipObjects +} + func (t *apiConfig) getListQuorum() int { t.mu.RLock() defer t.mu.RUnlock() diff --git a/cmd/object-handlers.go b/cmd/object-handlers.go index 1efa2db20..29e4290b5 100644 --- a/cmd/object-handlers.go +++ b/cmd/object-handlers.go @@ -37,6 +37,7 @@ import ( "github.com/google/uuid" "github.com/gorilla/mux" + "github.com/klauspost/compress/gzhttp" miniogo "github.com/minio/minio-go/v7" "github.com/minio/minio-go/v7/pkg/credentials" "github.com/minio/minio-go/v7/pkg/encrypt" @@ -568,6 +569,9 @@ func (api objectAPIHandlers) GetObjectHandler(w http.ResponseWriter, r *http.Req writeErrorResponse(ctx, w, toAPIError(ctx, err), r.URL) return } + if !globalAPIConfig.shouldGzipObjects() { + w.Header().Set(gzhttp.HeaderNoCompression, "true") + } if r.Header.Get(xMinIOExtract) == "true" && strings.Contains(object, archivePattern) { api.getObjectInArchiveFileHandler(ctx, objectAPI, bucket, object, w, r) diff --git a/internal/config/api/api.go b/internal/config/api/api.go index 372e8a507..aeb8739d4 100644 --- a/internal/config/api/api.go +++ b/internal/config/api/api.go @@ -44,6 +44,7 @@ const ( apiStaleUploadsExpiry = "stale_uploads_expiry" apiDeleteCleanupInterval = "delete_cleanup_interval" apiDisableODirect = "disable_odirect" + apiGzipObjects = "gzip_objects" EnvAPIRequestsMax = "MINIO_API_REQUESTS_MAX" EnvAPIRequestsDeadline = "MINIO_API_REQUESTS_DEADLINE" @@ -61,6 +62,7 @@ const ( EnvAPIDeleteCleanupInterval = "MINIO_API_DELETE_CLEANUP_INTERVAL" EnvDeleteCleanupInterval = "MINIO_DELETE_CLEANUP_INTERVAL" EnvAPIDisableODirect = "MINIO_API_DISABLE_ODIRECT" + EnvAPIGzipObjects = "MINIO_API_GZIP_OBJECTS" ) // Deprecated key and ENVs @@ -124,6 +126,10 @@ var ( Key: apiDisableODirect, Value: "off", }, + config.KV{ + Key: apiGzipObjects, + Value: "off", + }, } ) @@ -142,6 +148,7 @@ type Config struct { StaleUploadsExpiry time.Duration `json:"stale_uploads_expiry"` DeleteCleanupInterval time.Duration `json:"delete_cleanup_interval"` DisableODirect bool `json:"disable_odirect"` + GzipObjects bool `json:"gzip_objects"` } // UnmarshalJSON - Validate SS and RRS parity when unmarshalling JSON. @@ -263,6 +270,8 @@ func LookupConfig(kvs config.KVS) (cfg Config, err error) { disableODirect := env.Get(EnvAPIDisableODirect, kvs.Get(apiDisableODirect)) == config.EnableOn + gzipObjects := env.Get(EnvAPIGzipObjects, kvs.Get(apiGzipObjects)) == config.EnableOn + return Config{ RequestsMax: requestsMax, RequestsDeadline: requestsDeadline, @@ -277,5 +286,6 @@ func LookupConfig(kvs config.KVS) (cfg Config, err error) { StaleUploadsExpiry: staleUploadsExpiry, DeleteCleanupInterval: deleteCleanupInterval, DisableODirect: disableODirect, + GzipObjects: gzipObjects, }, nil }