Files
mostlymatter/services/imageproxy/imageproxy.go
Harrison Healey cbcfef25e5 MM-14574 Intercept log messages from local image proxy (#10668)
* MM-14574 Switch willnorris/imageproxy to fork

* MM-14574 Intercept log messages from local image proxy

* Revert "MM-14574 Switch willnorris/imageproxy to fork"

This reverts commit 046ab5c4216a5c6fee5bf8e2e0cceb1afffa6747.

* Update willnorris/imageproxy
2019-04-24 11:55:37 -04:00

147 строки
4.5 KiB
Go

// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package imageproxy
import (
"errors"
"io"
"net/http"
"sync"
"github.com/mattermost/mattermost-server/mlog"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/services/configservice"
"github.com/mattermost/mattermost-server/services/httpservice"
)
var ErrNotEnabled = Error{errors.New("imageproxy.ImageProxy: image proxy not enabled")}
// 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
Logger *mlog.Logger
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)
// GetImageDirect returns a proxied image along with its content type.
GetImageDirect(imageURL string) (io.ReadCloser, string, error)
// 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, logger *mlog.Logger) *ImageProxy {
proxy := &ImageProxy{
ConfigService: configService,
HTTPService: httpService,
Logger: logger,
}
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)
}
// GetImageDirect takes the URL of an image and returns the image along with its content type.
func (proxy *ImageProxy) GetImageDirect(imageURL string) (io.ReadCloser, string, error) {
proxy.lock.RLock()
defer proxy.lock.RUnlock()
if proxy.backend == nil {
return nil, "", ErrNotEnabled
}
return proxy.backend.GetImageDirect(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)
}