Switching redirect_location route to use httpservice client and adding caching. (#10118)

This commit is contained in:
Christopher Speller
2019-01-27 18:24:46 -08:00
committed by GitHub
parent b890f8d007
commit ce2c7110d3
2 changed files with 28 additions and 14 deletions

View File

@@ -14,8 +14,13 @@ import (
"github.com/mattermost/mattermost-server/mlog"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/services/filesstore"
"github.com/mattermost/mattermost-server/utils"
)
const REDIRECT_LOCATION_CACHE_SIZE = 10000
var redirectLocationDataCache = utils.NewLru(REDIRECT_LOCATION_CACHE_SIZE)
func (api *API) InitSystem() {
api.BaseRoutes.System.Handle("/ping", api.ApiHandler(getSystemPing)).Methods("GET")
@@ -471,32 +476,42 @@ func testS3(c *Context, w http.ResponseWriter, r *http.Request) {
func getRedirectLocation(c *Context, w http.ResponseWriter, r *http.Request) {
m := make(map[string]string)
m["location"] = ""
cfg := c.App.GetConfig()
if !*cfg.ServiceSettings.EnableLinkPreviews {
w.Write([]byte(model.MapToJson(m)))
return
}
url := r.URL.Query().Get("url")
if len(url) == 0 {
c.SetInvalidParam("url")
return
}
client := &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
res, err := client.Head(url)
if err != nil {
// Always return a success status and a JSON string to limit the amount of information returned to a
// hacker attempting to use Mattermost to probe a private network.
if location, ok := openGraphDataCache.Get(url); ok {
m["location"] = location.(string)
w.Write([]byte(model.MapToJson(m)))
return
}
m["location"] = res.Header.Get("Location")
client := c.App.HTTPService.MakeClient(false)
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
}
res, err := client.Head(url)
if err != nil {
// Cache failures to prevent retries.
redirectLocationDataCache.AddWithExpiresInSecs(url, "", 3600) // Expires after 1 hour
// Always return a success status and a JSON string to limit information returned to client.
w.Write([]byte(model.MapToJson(m)))
return
}
location := res.Header.Get("Location")
redirectLocationDataCache.AddWithExpiresInSecs(url, location, 3600) // Expires after 1 hour
m["location"] = location
w.Write([]byte(model.MapToJson(m)))
return

View File

@@ -751,6 +751,7 @@ func TestRedirectLocation(t *testing.T) {
}()
*th.App.Config().ServiceSettings.EnableLinkPreviews = true
*th.App.Config().ServiceSettings.AllowedUntrustedInternalConnections = "127.0.0.1"
_, resp := th.SystemAdminClient.GetRedirectLocation("https://mattermost.com/", "")
CheckNoError(t, resp)
@@ -760,9 +761,7 @@ func TestRedirectLocation(t *testing.T) {
actual, resp := th.SystemAdminClient.GetRedirectLocation(mockBitlyLink, "")
CheckNoError(t, resp)
if actual != expected {
t.Errorf("Expected %v but got %v.", expected, actual)
}
assert.Equal(t, expected, actual)
*th.App.Config().ServiceSettings.EnableLinkPreviews = false
actual, resp = th.SystemAdminClient.GetRedirectLocation("https://mattermost.com/", "")