MM-10417 Add local image proxy and enable by default (#9967)
* MM-10417 Add local image proxy and enable by default * Remove unused function * Add dependencies for willnorris/imageproxy * Fixed compilation errors * Lock to the master version of willnorris/imageproxy * Fix atmos/camo proxy when no SiteURL is specified * Re-add default values for deprecated settings * Fix unit tests added by merge * Pass imageproxy to App struct * Remove unneeded locking when creating the image proxy * Remove empty test file
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
e961b4cd0d
Коммит
ba5566d1a0
123
services/imageproxy/imageproxy.go
Обычный файл
123
services/imageproxy/imageproxy.go
Обычный файл
@@ -0,0 +1,123 @@
|
||||
// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
package imageproxy
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
"github.com/mattermost/mattermost-server/services/configservice"
|
||||
"github.com/mattermost/mattermost-server/services/httpservice"
|
||||
)
|
||||
|
||||
// An ImageProxy is the public interface for Mattermost's image proxy. An instance of ImageProxy should be created
|
||||
// using MakeImageProxy which requires a configService and an HTTPService provided by the server.
|
||||
type ImageProxy struct {
|
||||
ConfigService configservice.ConfigService
|
||||
configListenerId string
|
||||
|
||||
HTTPService httpservice.HTTPService
|
||||
|
||||
lock sync.RWMutex
|
||||
backend ImageProxyBackend
|
||||
}
|
||||
|
||||
// An ImageProxyBackend provides the functionality for different types of image proxies. An ImageProxy will construct
|
||||
// the required backend depending on the ImageProxySettings provided by the ConfigService.
|
||||
type ImageProxyBackend interface {
|
||||
// GetImage provides a proxied image in response to an HTTP request.
|
||||
GetImage(w http.ResponseWriter, r *http.Request, imageURL string)
|
||||
|
||||
// GetProxiedImageURL returns the URL to access a given image through the image proxy, whether the image proxy is
|
||||
// running externally or as part of the Mattermost server itself.
|
||||
GetProxiedImageURL(imageURL string) string
|
||||
|
||||
// GetUnproxiedImageURL returns the original URL of an image from one that has been directed at the image proxy.
|
||||
GetUnproxiedImageURL(proxiedURL string) string
|
||||
}
|
||||
|
||||
func MakeImageProxy(configService configservice.ConfigService, httpService httpservice.HTTPService) *ImageProxy {
|
||||
proxy := &ImageProxy{
|
||||
ConfigService: configService,
|
||||
HTTPService: httpService,
|
||||
}
|
||||
|
||||
proxy.configListenerId = proxy.ConfigService.AddConfigListener(proxy.OnConfigChange)
|
||||
|
||||
config := proxy.ConfigService.Config()
|
||||
proxy.backend = proxy.makeBackend(*config.ImageProxySettings.Enable, *config.ImageProxySettings.ImageProxyType)
|
||||
|
||||
return proxy
|
||||
}
|
||||
|
||||
func (proxy *ImageProxy) makeBackend(enable bool, proxyType string) ImageProxyBackend {
|
||||
if !enable {
|
||||
return nil
|
||||
}
|
||||
|
||||
switch proxyType {
|
||||
case model.IMAGE_PROXY_TYPE_LOCAL:
|
||||
return makeLocalBackend(proxy)
|
||||
case model.IMAGE_PROXY_TYPE_ATMOS_CAMO:
|
||||
return makeAtmosCamoBackend(proxy)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (proxy *ImageProxy) Close() {
|
||||
proxy.lock.Lock()
|
||||
defer proxy.lock.Unlock()
|
||||
|
||||
proxy.ConfigService.RemoveConfigListener(proxy.configListenerId)
|
||||
}
|
||||
|
||||
func (proxy *ImageProxy) OnConfigChange(oldConfig, newConfig *model.Config) {
|
||||
if *oldConfig.ImageProxySettings.Enable != *newConfig.ImageProxySettings.Enable ||
|
||||
*oldConfig.ImageProxySettings.ImageProxyType != *newConfig.ImageProxySettings.ImageProxyType {
|
||||
proxy.lock.Lock()
|
||||
defer proxy.lock.Unlock()
|
||||
|
||||
proxy.backend = proxy.makeBackend(*newConfig.ImageProxySettings.Enable, *newConfig.ImageProxySettings.ImageProxyType)
|
||||
}
|
||||
}
|
||||
|
||||
// GetImage takes an HTTP request for an image and requests that image using the image proxy.
|
||||
func (proxy *ImageProxy) GetImage(w http.ResponseWriter, r *http.Request, imageURL string) {
|
||||
proxy.lock.RLock()
|
||||
defer proxy.lock.RUnlock()
|
||||
|
||||
if proxy.backend == nil {
|
||||
w.WriteHeader(http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
|
||||
proxy.backend.GetImage(w, r, imageURL)
|
||||
}
|
||||
|
||||
// GetProxiedImageURL takes the URL of an image and returns a URL that can be used to view that image through the
|
||||
// image proxy.
|
||||
func (proxy *ImageProxy) GetProxiedImageURL(imageURL string) string {
|
||||
proxy.lock.RLock()
|
||||
defer proxy.lock.RUnlock()
|
||||
|
||||
if proxy.backend == nil {
|
||||
return imageURL
|
||||
}
|
||||
|
||||
return proxy.backend.GetProxiedImageURL(imageURL)
|
||||
}
|
||||
|
||||
// GetUnproxiedImageURL takes the URL of an image on the image proxy and returns the original URL of the image.
|
||||
func (proxy *ImageProxy) GetUnproxiedImageURL(proxiedURL string) string {
|
||||
proxy.lock.RLock()
|
||||
defer proxy.lock.RUnlock()
|
||||
|
||||
if proxy.backend == nil {
|
||||
return proxiedURL
|
||||
}
|
||||
|
||||
return proxy.backend.GetUnproxiedImageURL(proxiedURL)
|
||||
}
|
||||
Ссылка в новой задаче
Block a user