github.com/ashishbhate/mattermost-server@v5.11.1+incompatible/services/imageproxy/atmos_camo.go (about)

     1  // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package imageproxy
     5  
     6  import (
     7  	"crypto/hmac"
     8  	"crypto/sha1"
     9  	"encoding/hex"
    10  	"io"
    11  	"net/http"
    12  	"strings"
    13  )
    14  
    15  type AtmosCamoBackend struct {
    16  	proxy *ImageProxy
    17  }
    18  
    19  func makeAtmosCamoBackend(proxy *ImageProxy) *AtmosCamoBackend {
    20  	return &AtmosCamoBackend{
    21  		proxy: proxy,
    22  	}
    23  }
    24  
    25  func (backend *AtmosCamoBackend) GetImage(w http.ResponseWriter, r *http.Request, imageURL string) {
    26  	http.Redirect(w, r, backend.GetProxiedImageURL(imageURL), http.StatusFound)
    27  }
    28  
    29  func (backend *AtmosCamoBackend) GetImageDirect(imageURL string) (io.ReadCloser, string, error) {
    30  	req, err := http.NewRequest("GET", backend.GetProxiedImageURL(imageURL), nil)
    31  	if err != nil {
    32  		return nil, "", Error{err}
    33  	}
    34  
    35  	client := backend.proxy.HTTPService.MakeClient(false)
    36  
    37  	resp, err := client.Do(req)
    38  	if err != nil {
    39  		return nil, "", Error{err}
    40  	}
    41  
    42  	// Note that we don't do any additional validation of the received data since we expect the image proxy to do that
    43  	return resp.Body, resp.Header.Get("Content-Type"), nil
    44  }
    45  
    46  func (backend *AtmosCamoBackend) GetProxiedImageURL(imageURL string) string {
    47  	cfg := *backend.proxy.ConfigService.Config()
    48  	siteURL := *cfg.ServiceSettings.SiteURL
    49  	proxyURL := *cfg.ImageProxySettings.RemoteImageProxyURL
    50  	options := *cfg.ImageProxySettings.RemoteImageProxyOptions
    51  
    52  	return getAtmosCamoImageURL(imageURL, siteURL, proxyURL, options)
    53  }
    54  
    55  func getAtmosCamoImageURL(imageURL, siteURL, proxyURL, options string) string {
    56  	// Don't proxy blank images, relative URLs, absolute URLs on this server, or URLs that are already going through the proxy
    57  	if imageURL == "" || imageURL[0] == '/' || (siteURL != "" && strings.HasPrefix(imageURL, siteURL)) || strings.HasPrefix(imageURL, proxyURL) {
    58  		return imageURL
    59  	}
    60  
    61  	mac := hmac.New(sha1.New, []byte(options))
    62  	mac.Write([]byte(imageURL))
    63  	digest := hex.EncodeToString(mac.Sum(nil))
    64  
    65  	return proxyURL + "/" + digest + "/" + hex.EncodeToString([]byte(imageURL))
    66  }
    67  
    68  func (backend *AtmosCamoBackend) GetUnproxiedImageURL(proxiedURL string) string {
    69  	proxyURL := *backend.proxy.ConfigService.Config().ImageProxySettings.RemoteImageProxyURL + "/"
    70  
    71  	if !strings.HasPrefix(proxiedURL, proxyURL) {
    72  		return proxiedURL
    73  	}
    74  
    75  	path := proxiedURL[len(proxyURL):]
    76  
    77  	slash := strings.IndexByte(path, '/')
    78  	if slash == -1 {
    79  		return proxiedURL
    80  	}
    81  
    82  	decoded, err := hex.DecodeString(path[slash+1:])
    83  	if err != nil {
    84  		return proxiedURL
    85  	}
    86  
    87  	return string(decoded)
    88  }