MM-13838 Bypass the HTTP client when getting image dimensions from the image proxy (#10208)
* MM-13838 Bypass the HTTP client when getting image dimensions from the proxy * Add additional log messages to debug failing test * Fix unit test to work on Jenkins
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
85c60f1402
Коммит
dbf54b3599
@@ -346,18 +346,34 @@ func (a *App) getLinkMetadata(requestURL string, timestamp int64, isNewPost bool
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
request.Header.Add("Accept", "text/html, image/*")
|
||||
var body io.ReadCloser
|
||||
var contentType string
|
||||
|
||||
client := a.HTTPService.MakeClient(false)
|
||||
client.Timeout = time.Duration(*a.Config().ExperimentalSettings.LinkMetadataTimeoutMilliseconds) * time.Millisecond
|
||||
if (request.URL.Scheme+"://"+request.URL.Host) == a.GetSiteURL() && request.URL.Path == "/api/v4/image" {
|
||||
// /api/v4/image requires authentication, so bypass the API by hitting the proxy directly
|
||||
body, contentType, err = a.ImageProxy.GetImageDirect(a.ImageProxy.GetUnproxiedImageURL(request.URL.String()))
|
||||
} else {
|
||||
request.Header.Add("Accept", "text/html, image/*")
|
||||
|
||||
res, err := client.Do(request)
|
||||
client := a.HTTPService.MakeClient(false)
|
||||
client.Timeout = time.Duration(*a.Config().ExperimentalSettings.LinkMetadataTimeoutMilliseconds) * time.Millisecond
|
||||
|
||||
var res *http.Response
|
||||
res, err = client.Do(request)
|
||||
|
||||
if res != nil {
|
||||
body = res.Body
|
||||
contentType = res.Header.Get("Content-Type")
|
||||
}
|
||||
}
|
||||
|
||||
if body != nil {
|
||||
defer body.Close()
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
defer res.Body.Close()
|
||||
|
||||
// Parse the data
|
||||
og, image, err = a.parseLinkMetadata(requestURL, res.Body, res.Header.Get("Content-Type"))
|
||||
og, image, err = a.parseLinkMetadata(requestURL, body, contentType)
|
||||
}
|
||||
|
||||
// Write back to cache and database, even if there was an error and the results are nil
|
||||
|
||||
@@ -19,6 +19,8 @@ import (
|
||||
|
||||
"github.com/dyatlov/go-opengraph/opengraph"
|
||||
"github.com/mattermost/mattermost-server/model"
|
||||
"github.com/mattermost/mattermost-server/services/httpservice"
|
||||
"github.com/mattermost/mattermost-server/services/imageproxy"
|
||||
"github.com/mattermost/mattermost-server/utils/testutils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -1064,8 +1066,6 @@ func TestGetLinkMetadata(t *testing.T) {
|
||||
|
||||
return th
|
||||
}
|
||||
th := Setup().InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
params := r.URL.Query()
|
||||
@@ -1510,6 +1510,11 @@ func TestGetLinkMetadata(t *testing.T) {
|
||||
defer th.TearDown()
|
||||
|
||||
// Fake the SiteURL to have the relative URL resolve to the external server
|
||||
oldSiteURL := *th.App.Config().ServiceSettings.SiteURL
|
||||
defer th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.SiteURL = oldSiteURL
|
||||
})
|
||||
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.SiteURL = server.URL
|
||||
})
|
||||
@@ -1522,6 +1527,45 @@ func TestGetLinkMetadata(t *testing.T) {
|
||||
assert.NotNil(t, img)
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
|
||||
t.Run("should error on local addresses other than the image proxy", func(t *testing.T) {
|
||||
th := setup()
|
||||
defer th.TearDown()
|
||||
|
||||
// Disable AllowedUntrustedInternalConnections since it's turned on for the previous tests
|
||||
oldAllowUntrusted := *th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections
|
||||
oldSiteURL := *th.App.Config().ServiceSettings.SiteURL
|
||||
defer th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = oldAllowUntrusted
|
||||
*cfg.ServiceSettings.SiteURL = oldSiteURL
|
||||
})
|
||||
|
||||
th.App.UpdateConfig(func(cfg *model.Config) {
|
||||
*cfg.ServiceSettings.AllowedUntrustedInternalConnections = ""
|
||||
*cfg.ServiceSettings.SiteURL = "http://mattermost.example.com"
|
||||
*cfg.ImageProxySettings.Enable = true
|
||||
*cfg.ImageProxySettings.ImageProxyType = "local"
|
||||
})
|
||||
|
||||
requestURL := server.URL + "/image?height=200&width=300&name=" + t.Name()
|
||||
timestamp := int64(1547510400000)
|
||||
|
||||
og, img, err := th.App.getLinkMetadata(requestURL, timestamp, false)
|
||||
assert.Nil(t, og)
|
||||
assert.Nil(t, img)
|
||||
assert.NotNil(t, err)
|
||||
assert.IsType(t, &url.Error{}, err)
|
||||
assert.Equal(t, httpservice.AddressForbidden, err.(*url.Error).Err)
|
||||
|
||||
requestURL = th.App.GetSiteURL() + "/api/v4/image?url=" + url.QueryEscape(requestURL)
|
||||
|
||||
// Note that this request still fails while testing because the request made by the image proxy is blocked
|
||||
og, img, err = th.App.getLinkMetadata(requestURL, timestamp, false)
|
||||
assert.Nil(t, og)
|
||||
assert.Nil(t, img)
|
||||
assert.NotNil(t, err)
|
||||
assert.IsType(t, imageproxy.Error{}, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestResolveMetadataURL(t *testing.T) {
|
||||
|
||||
Ссылка в новой задаче
Block a user