From e4596e217104db1e9252ce4d669d1409c8a4ad5a Mon Sep 17 00:00:00 2001 From: Travis Ralston <travpc@gmail.com> Date: Sat, 29 Feb 2020 22:42:17 -0700 Subject: [PATCH] Add a config for blurhash --- api/custom/version.go | 11 ++++---- api/r0/upload.go | 14 ++++++++--- api/webserver/webserver.go | 5 ++-- common/config/conf_min_shared.go | 13 ++++++++++ common/config/models_domain.go | 15 +++++++++++ common/config/watch.go | 11 +++++++- config.sample.yaml | 25 +++++++++++++++++++ .../info_controller/info_controller.go | 4 +-- docs/config.md | 3 +++ 9 files changed, 87 insertions(+), 14 deletions(-) diff --git a/api/custom/version.go b/api/custom/version.go index 85b79695..d5ac8e6d 100644 --- a/api/custom/version.go +++ b/api/custom/version.go @@ -9,13 +9,14 @@ import ( ) func GetVersion(r *http.Request, rctx rcontext.RequestContext, user api.UserInfo) interface{} { + unstableFeatures := make(map[string]bool) + unstableFeatures["xyz.amorgan.blurhash"] = rctx.Config.Features.MSC2448Blurhash.Enabled + return &api.DoNotCacheResponse{ Payload: map[string]interface{}{ - "Version": version.Version, - "GitCommit": version.GitCommit, - "unstable_features": []string{ - "xyz.amorgan.blurhash", - }, + "Version": version.Version, + "GitCommit": version.GitCommit, + "unstable_features": unstableFeatures, }, } } diff --git a/api/r0/upload.go b/api/r0/upload.go index 4b669271..20518131 100644 --- a/api/r0/upload.go +++ b/api/r0/upload.go @@ -58,13 +58,19 @@ func UploadMedia(r *http.Request, rctx rcontext.RequestContext, user api.UserInf return api.InternalServerError("Unexpected Error") } - hash, err := info_controller.GetOrCalculateBlurhash(media, rctx) - if err != nil { - rctx.Log.Warn("Failed to calculate blurhash: " + err.Error()) + if rctx.Config.Features.MSC2448Blurhash.Enabled { + hash, err := info_controller.GetOrCalculateBlurhash(media, rctx) + if err != nil { + rctx.Log.Warn("Failed to calculate blurhash: " + err.Error()) + } + + return &MediaUploadedResponse{ + ContentUri: media.MxcUri(), + Blurhash: hash, + } } return &MediaUploadedResponse{ ContentUri: media.MxcUri(), - Blurhash: hash, } } diff --git a/api/webserver/webserver.go b/api/webserver/webserver.go index 86b5c3d3..822381e5 100644 --- a/api/webserver/webserver.go +++ b/api/webserver/webserver.go @@ -135,8 +135,9 @@ func Init() *sync.WaitGroup { routes["/_matrix/media/"+version+"/info/{server:[a-zA-Z0-9.:\\-_]+}/{mediaId:[a-zA-Z0-9.\\-_]+}"] = route{"GET", infoHandler} routes["/_matrix/media/"+version+"/download/{server:[a-zA-Z0-9.:\\-_]+}/{mediaId:[a-zA-Z0-9.\\-_]+}"] = route{"DELETE", purgeOneHandler} - // MSC2448: Blurhash - routes["/_matrix/media/"+version+"/xyz.amorgan/upload"] = route{"POST", uploadHandler} + if config.Get().Features.MSC2448Blurhash.Enabled { + routes["/_matrix/media/"+version+"/xyz.amorgan/upload"] = route{"POST", uploadHandler} + } } } diff --git a/common/config/conf_min_shared.go b/common/config/conf_min_shared.go index 44ef3fcd..d2e1ada1 100644 --- a/common/config/conf_min_shared.go +++ b/common/config/conf_min_shared.go @@ -7,6 +7,7 @@ type MinimumRepoConfig struct { Identicons IdenticonsConfig `yaml:"identicons"` Quarantine QuarantineConfig `yaml:"quarantine"` TimeoutSeconds TimeoutsConfig `yaml:"timeouts"` + Features FeatureConfig `yaml:"featureSupport"` } func NewDefaultMinimumRepoConfig() MinimumRepoConfig { @@ -38,5 +39,17 @@ func NewDefaultMinimumRepoConfig() MinimumRepoConfig { ClientServer: 30, Federation: 120, }, + Features: FeatureConfig{ + MSC2448Blurhash: MSC2448Config{ + Enabled: false, + MaxRenderWidth: 1024, + MaxRenderHeight: 1024, + GenerateWidth: 64, + GenerateHeight: 64, + XComponents: 4, + YComponents: 3, + Punch: 1, + }, + }, } } diff --git a/common/config/models_domain.go b/common/config/models_domain.go index 98d60c9a..6c11d72b 100644 --- a/common/config/models_domain.go +++ b/common/config/models_domain.go @@ -72,3 +72,18 @@ type TimeoutsConfig struct { Federation int `yaml:"federationTimeoutSeconds"` ClientServer int `yaml:"clientServerTimeoutSeconds"` } + +type FeatureConfig struct { + MSC2448Blurhash MSC2448Config `yaml:"MSC2448"` +} + +type MSC2448Config struct { + Enabled bool `yaml:"enabled"` + MaxRenderWidth int `yaml:"maxWidth"` + MaxRenderHeight int `yaml:"maxHeight"` + GenerateWidth int `yaml:"thumbWidth"` + GenerateHeight int `yaml:"thumbHeight"` + XComponents int `yaml:"xComponents"` + YComponents int `yaml:"yComponents"` + Punch int `yaml:"punch"` +} diff --git a/common/config/watch.go b/common/config/watch.go index 1e64ff8c..62c8fd92 100644 --- a/common/config/watch.go +++ b/common/config/watch.go @@ -60,7 +60,8 @@ func onFileChanged() { bindPortChange := configNew.General.Port != configNow.General.Port forwardAddressChange := configNew.General.TrustAnyForward != configNow.General.TrustAnyForward forwardedHostChange := configNew.General.UseForwardedHost != configNow.General.UseForwardedHost - if bindAddressChange || bindPortChange || forwardAddressChange || forwardedHostChange { + featureChanged := hasWebFeatureChanged(configNew, configNow) + if bindAddressChange || bindPortChange || forwardAddressChange || forwardedHostChange || featureChanged { logrus.Warn("Webserver configuration changed - remounting") globals.WebReloadChan <- true } @@ -93,3 +94,11 @@ func onFileChanged() { logrus.Info("Restarting recurring tasks") globals.RecurringTasksReloadChan <- true } + +func hasWebFeatureChanged(configNew *MainRepoConfig, configNow *MainRepoConfig) bool { + if configNew.Features.MSC2448Blurhash.Enabled != configNow.Features.MSC2448Blurhash.Enabled { + return true + } + + return false +} diff --git a/config.sample.yaml b/config.sample.yaml index b6df78cc..4b0f87f5 100644 --- a/config.sample.yaml +++ b/config.sample.yaml @@ -392,3 +392,28 @@ metrics: # The port to listen on. Cannot be the same as the general web server port. port: 9000 + +# Options for controlling various MSCs/unstable features of the media repo +# Sections of this config might disappear or be added over time. By default all +# features are disabled in here and must be explicitly enabled to be used. +featureSupport: + # MSC2248 - Blurhash + MSC2448: + # Whether or not this MSC is enabled for use in the media repo + enabled: false + + # Maximum dimensions for converting a blurhash to an image + maxWidth: 1024 + maxHeight: 1024 + + # Thumbnail size in pixels to use to generate the blurhash string + thumbWidth: 64 + thumbHeight: 64 + + # The X and Y components to use. Higher numbers blur less, lower numbers blur more. + xComponents: 4 + yComponents: 3 + + # The amount of contrast to apply when converting a blurhash to an image. Lower values + # make the effect more subtle, larger values make it stronger. + punch: 1 diff --git a/controllers/info_controller/info_controller.go b/controllers/info_controller/info_controller.go index 223fe325..69c7eb46 100644 --- a/controllers/info_controller/info_controller.go +++ b/controllers/info_controller/info_controller.go @@ -40,7 +40,7 @@ func GetOrCalculateBlurhash(media *types.Media, rctx rcontext.RequestContext) (s // Resize the image to make the blurhash a bit more reasonable to calculate rctx.Log.Info("Resizing image for blurhash (faster calculation)") - smallImg := imaging.Fill(imgSrc, 128, 128, imaging.Center, imaging.Lanczos) + smallImg := imaging.Fill(imgSrc, rctx.Config.Features.MSC2448Blurhash.GenerateWidth, rctx.Config.Features.MSC2448Blurhash.GenerateHeight, imaging.Center, imaging.Lanczos) imgBuf := &bytes.Buffer{} err = imaging.Encode(imgBuf, smallImg, imaging.PNG) if err != nil { @@ -52,7 +52,7 @@ func GetOrCalculateBlurhash(media *types.Media, rctx rcontext.RequestContext) (s } rctx.Log.Info("Calculating blurhash") - encoded, err := blurhash.Encode(4, 3, &decoded) + encoded, err := blurhash.Encode(rctx.Config.Features.MSC2448Blurhash.XComponents, rctx.Config.Features.MSC2448Blurhash.YComponents, &decoded) if err != nil { return "", err } diff --git a/docs/config.md b/docs/config.md index f316436b..0e98b63d 100644 --- a/docs/config.md +++ b/docs/config.md @@ -65,3 +65,6 @@ identicons: Per-domain configs can also be layered - just ensure that each layer has the `homeserver` property in it. They inherit from the main config for options not defined in their layers. + +Note: all feature configs which require webserver routes to be added will need to be additionally defined in the main +config as enabled or disabled, then turned on and off for individual domains. -- GitLab