MM-11786: Adds API endpoint to retrieve redirect locations. (#9284)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
f9dbea6d86
Коммит
ed0fb617ef
@@ -40,6 +40,8 @@ func (api *API) InitSystem() {
|
|||||||
api.BaseRoutes.ApiRoot.Handle("/logs", api.ApiHandler(postLog)).Methods("POST")
|
api.BaseRoutes.ApiRoot.Handle("/logs", api.ApiHandler(postLog)).Methods("POST")
|
||||||
|
|
||||||
api.BaseRoutes.ApiRoot.Handle("/analytics/old", api.ApiSessionRequired(getAnalytics)).Methods("GET")
|
api.BaseRoutes.ApiRoot.Handle("/analytics/old", api.ApiSessionRequired(getAnalytics)).Methods("GET")
|
||||||
|
|
||||||
|
api.BaseRoutes.ApiRoot.Handle("/redirect_location", api.ApiSessionRequiredTrustRequester(getRedirectLocation)).Methods("GET")
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSystemPing(c *Context, w http.ResponseWriter, r *http.Request) {
|
func getSystemPing(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -447,3 +449,33 @@ func testS3(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
ReturnStatusOK(w)
|
ReturnStatusOK(w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getRedirectLocation(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||||
|
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
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
m := make(map[string]string)
|
||||||
|
m["location"] = ""
|
||||||
|
|
||||||
|
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.
|
||||||
|
w.Write([]byte(model.MapToJson(m)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m["location"] = res.Header.Get("Location")
|
||||||
|
|
||||||
|
w.Write([]byte(model.MapToJson(m)))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package api4
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -700,3 +701,36 @@ func TestSupportedTimezones(t *testing.T) {
|
|||||||
CheckNoError(t, resp)
|
CheckNoError(t, resp)
|
||||||
assert.Equal(t, supportedTimezonesFromConfig, supportedTimezones)
|
assert.Equal(t, supportedTimezonesFromConfig, supportedTimezones)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRedirectLocation(t *testing.T) {
|
||||||
|
expected := "https://mattermost.com/wp-content/themes/mattermostv2/img/logo-light.svg"
|
||||||
|
|
||||||
|
testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
|
||||||
|
res.Header().Set("Location", expected)
|
||||||
|
res.WriteHeader(http.StatusFound)
|
||||||
|
res.Write([]byte("body"))
|
||||||
|
}))
|
||||||
|
defer func() { testServer.Close() }()
|
||||||
|
|
||||||
|
mockBitlyLink := testServer.URL
|
||||||
|
|
||||||
|
th := Setup().InitBasic().InitSystemAdmin()
|
||||||
|
defer th.TearDown()
|
||||||
|
Client := th.Client
|
||||||
|
|
||||||
|
_, resp := th.SystemAdminClient.GetRedirectLocation("https://mattermost.com/", "")
|
||||||
|
CheckNoError(t, resp)
|
||||||
|
|
||||||
|
_, resp = th.SystemAdminClient.GetRedirectLocation("", "")
|
||||||
|
CheckBadRequestStatus(t, resp)
|
||||||
|
|
||||||
|
actual, resp := th.SystemAdminClient.GetRedirectLocation(mockBitlyLink, "")
|
||||||
|
CheckNoError(t, resp)
|
||||||
|
if actual != expected {
|
||||||
|
t.Errorf("Expected %v but got %v.", expected, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
Client.Logout()
|
||||||
|
_, resp = Client.GetRedirectLocation("", "")
|
||||||
|
CheckUnauthorizedStatus(t, resp)
|
||||||
|
}
|
||||||
|
|||||||
@@ -397,6 +397,10 @@ func (c *Client4) GetTotalUsersStatsRoute() string {
|
|||||||
return fmt.Sprintf(c.GetUsersRoute() + "/stats")
|
return fmt.Sprintf(c.GetUsersRoute() + "/stats")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client4) GetRedirectLocationRoute() string {
|
||||||
|
return fmt.Sprintf("/redirect_location")
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client4) DoApiGet(url string, etag string) (*http.Response, *AppError) {
|
func (c *Client4) DoApiGet(url string, etag string) (*http.Response, *AppError) {
|
||||||
return c.DoApiRequest(http.MethodGet, c.ApiUrl+url, "", etag)
|
return c.DoApiRequest(http.MethodGet, c.ApiUrl+url, "", etag)
|
||||||
}
|
}
|
||||||
@@ -3771,3 +3775,14 @@ func (c *Client4) UpdateTeamScheme(teamId, schemeId string) (bool, *Response) {
|
|||||||
return CheckStatusOK(r), BuildResponse(r)
|
return CheckStatusOK(r), BuildResponse(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRedirectLocation retrieves the value of the 'Location' header of an HTTP response for a given URL.
|
||||||
|
func (c *Client4) GetRedirectLocation(urlParam, etag string) (string, *Response) {
|
||||||
|
url := fmt.Sprintf("%s?url=%s", c.GetRedirectLocationRoute(), url.QueryEscape(urlParam))
|
||||||
|
if r, err := c.DoApiGet(url, etag); err != nil {
|
||||||
|
return "", BuildErrorResponse(r, err)
|
||||||
|
} else {
|
||||||
|
defer closeBody(r)
|
||||||
|
return MapFromJson(r.Body)["location"], BuildResponse(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user