* Improve API4 initialization

- Refactored openGraphDataCache to be inside app layer.
- Moved the cache instance from global variable to be inside server.
- Moved out the app instantiation from the global commands package
to be instantiated on every call. Only the server instance is passed.
- Moved InitLocal to be called from inside Init.

```release-note
NONE
```

* Remove commented line

```release-note
NONE
```
Этот коммит содержится в:
Agniva De Sarker
2021-10-15 19:57:05 +05:30
коммит произвёл GitHub
родитель 43a99a5783
Коммит c27814393d
18 изменённых файлов: 139 добавлений и 122 удалений

Просмотреть файл

@@ -135,18 +135,18 @@ type Routes struct {
} }
type API struct { type API struct {
app app.AppIface srv *app.Server
BaseRoutes *Routes BaseRoutes *Routes
} }
func Init(a app.AppIface, root *mux.Router) *API { func Init(srv *app.Server) *API {
api := &API{ api := &API{
app: a, srv: srv,
BaseRoutes: &Routes{}, BaseRoutes: &Routes{},
} }
api.BaseRoutes.Root = root api.BaseRoutes.Root = srv.Router
api.BaseRoutes.APIRoot = root.PathPrefix(model.APIURLSuffix).Subrouter() api.BaseRoutes.APIRoot = srv.Router.PathPrefix(model.APIURLSuffix).Subrouter()
api.BaseRoutes.Users = api.BaseRoutes.APIRoot.PathPrefix("/users").Subrouter() api.BaseRoutes.Users = api.BaseRoutes.APIRoot.PathPrefix("/users").Subrouter()
api.BaseRoutes.User = api.BaseRoutes.APIRoot.PathPrefix("/users/{user_id:[A-Za-z0-9]+}").Subrouter() api.BaseRoutes.User = api.BaseRoutes.APIRoot.PathPrefix("/users/{user_id:[A-Za-z0-9]+}").Subrouter()
@@ -293,19 +293,21 @@ func Init(a app.AppIface, root *mux.Router) *API {
api.InitPermissions() api.InitPermissions()
api.InitExport() api.InitExport()
root.Handle("/api/v4/{anything:.*}", http.HandlerFunc(api.Handle404)) srv.Router.Handle("/api/v4/{anything:.*}", http.HandlerFunc(api.Handle404))
InitLocal(srv)
return api return api
} }
func InitLocal(a app.AppIface, root *mux.Router) *API { func InitLocal(srv *app.Server) *API {
api := &API{ api := &API{
app: a, srv: srv,
BaseRoutes: &Routes{}, BaseRoutes: &Routes{},
} }
api.BaseRoutes.Root = root api.BaseRoutes.Root = srv.LocalRouter
api.BaseRoutes.APIRoot = root.PathPrefix(model.APIURLSuffix).Subrouter() api.BaseRoutes.APIRoot = srv.LocalRouter.PathPrefix(model.APIURLSuffix).Subrouter()
api.BaseRoutes.Users = api.BaseRoutes.APIRoot.PathPrefix("/users").Subrouter() api.BaseRoutes.Users = api.BaseRoutes.APIRoot.PathPrefix("/users").Subrouter()
api.BaseRoutes.User = api.BaseRoutes.Users.PathPrefix("/{user_id:[A-Za-z0-9]+}").Subrouter() api.BaseRoutes.User = api.BaseRoutes.Users.PathPrefix("/{user_id:[A-Za-z0-9]+}").Subrouter()
@@ -386,13 +388,14 @@ func InitLocal(a app.AppIface, root *mux.Router) *API {
api.InitJobLocal() api.InitJobLocal()
api.InitSamlLocal() api.InitSamlLocal()
root.Handle("/api/v4/{anything:.*}", http.HandlerFunc(api.Handle404)) srv.LocalRouter.Handle("/api/v4/{anything:.*}", http.HandlerFunc(api.Handle404))
return api return api
} }
func (api *API) Handle404(w http.ResponseWriter, r *http.Request) { func (api *API) Handle404(w http.ResponseWriter, r *http.Request) {
web.Handle404(api.app, w, r) app := app.New(app.ServerConnector(api.srv.Channels()))
web.Handle404(app, w, r)
} }
var ReturnStatusOK = web.ReturnStatusOK var ReturnStatusOK = web.ReturnStatusOK

Просмотреть файл

@@ -177,9 +177,8 @@ func setupTestHelper(dbStore store.Store, searchEngine *searchengine.Broker, ent
panic(err) panic(err)
} }
Init(th.App, th.App.Srv().Router) Init(th.App.Srv())
InitLocal(th.App, th.App.Srv().LocalRouter) web.New(th.App.Srv())
web.New(th.App, th.App.Srv().Router)
wsapi.Init(th.App.Srv()) wsapi.Init(th.App.Srv())
if enterprise { if enterprise {

Просмотреть файл

@@ -17,7 +17,7 @@ type Context = web.Context
// granted. // granted.
func (api *API) APIHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { func (api *API) APIHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
handler := &web.Handler{ handler := &web.Handler{
App: api.app, Srv: api.srv,
HandleFunc: h, HandleFunc: h,
HandlerName: web.GetHandlerName(h), HandlerName: web.GetHandlerName(h),
RequireSession: false, RequireSession: false,
@@ -26,7 +26,7 @@ func (api *API) APIHandler(h func(*Context, http.ResponseWriter, *http.Request))
IsStatic: false, IsStatic: false,
IsLocal: false, IsLocal: false,
} }
if *api.app.Config().ServiceSettings.WebserverMode == "gzip" { if *api.srv.Config().ServiceSettings.WebserverMode == "gzip" {
return gziphandler.GzipHandler(handler) return gziphandler.GzipHandler(handler)
} }
return handler return handler
@@ -36,7 +36,7 @@ func (api *API) APIHandler(h func(*Context, http.ResponseWriter, *http.Request))
// be granted. // be granted.
func (api *API) APISessionRequired(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { func (api *API) APISessionRequired(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
handler := &web.Handler{ handler := &web.Handler{
App: api.app, Srv: api.srv,
HandleFunc: h, HandleFunc: h,
HandlerName: web.GetHandlerName(h), HandlerName: web.GetHandlerName(h),
RequireSession: true, RequireSession: true,
@@ -45,7 +45,7 @@ func (api *API) APISessionRequired(h func(*Context, http.ResponseWriter, *http.R
IsStatic: false, IsStatic: false,
IsLocal: false, IsLocal: false,
} }
if *api.app.Config().ServiceSettings.WebserverMode == "gzip" { if *api.srv.Config().ServiceSettings.WebserverMode == "gzip" {
return gziphandler.GzipHandler(handler) return gziphandler.GzipHandler(handler)
} }
return handler return handler
@@ -55,7 +55,7 @@ func (api *API) APISessionRequired(h func(*Context, http.ResponseWriter, *http.R
// CloudAPIKeyRequired provides a handler for webhook endpoints to access Cloud installations from CWS // CloudAPIKeyRequired provides a handler for webhook endpoints to access Cloud installations from CWS
func (api *API) CloudAPIKeyRequired(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { func (api *API) CloudAPIKeyRequired(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
handler := &web.Handler{ handler := &web.Handler{
App: api.app, Srv: api.srv,
HandleFunc: h, HandleFunc: h,
HandlerName: web.GetHandlerName(h), HandlerName: web.GetHandlerName(h),
RequireSession: false, RequireSession: false,
@@ -65,7 +65,7 @@ func (api *API) CloudAPIKeyRequired(h func(*Context, http.ResponseWriter, *http.
IsStatic: false, IsStatic: false,
IsLocal: false, IsLocal: false,
} }
if *api.app.Config().ServiceSettings.WebserverMode == "gzip" { if *api.srv.Config().ServiceSettings.WebserverMode == "gzip" {
return gziphandler.GzipHandler(handler) return gziphandler.GzipHandler(handler)
} }
return handler return handler
@@ -75,7 +75,7 @@ func (api *API) CloudAPIKeyRequired(h func(*Context, http.ResponseWriter, *http.
// RemoteClusterTokenRequired provides a handler for remote cluster requests to /remotecluster endpoints. // RemoteClusterTokenRequired provides a handler for remote cluster requests to /remotecluster endpoints.
func (api *API) RemoteClusterTokenRequired(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { func (api *API) RemoteClusterTokenRequired(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
handler := &web.Handler{ handler := &web.Handler{
App: api.app, Srv: api.srv,
HandleFunc: h, HandleFunc: h,
HandlerName: web.GetHandlerName(h), HandlerName: web.GetHandlerName(h),
RequireSession: false, RequireSession: false,
@@ -86,7 +86,7 @@ func (api *API) RemoteClusterTokenRequired(h func(*Context, http.ResponseWriter,
IsStatic: false, IsStatic: false,
IsLocal: false, IsLocal: false,
} }
if *api.app.Config().ServiceSettings.WebserverMode == "gzip" { if *api.srv.Config().ServiceSettings.WebserverMode == "gzip" {
return gziphandler.GzipHandler(handler) return gziphandler.GzipHandler(handler)
} }
return handler return handler
@@ -97,7 +97,7 @@ func (api *API) RemoteClusterTokenRequired(h func(*Context, http.ResponseWriter,
// authentication must be waived. // authentication must be waived.
func (api *API) APISessionRequiredMfa(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { func (api *API) APISessionRequiredMfa(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
handler := &web.Handler{ handler := &web.Handler{
App: api.app, Srv: api.srv,
HandleFunc: h, HandleFunc: h,
HandlerName: web.GetHandlerName(h), HandlerName: web.GetHandlerName(h),
RequireSession: true, RequireSession: true,
@@ -106,7 +106,7 @@ func (api *API) APISessionRequiredMfa(h func(*Context, http.ResponseWriter, *htt
IsStatic: false, IsStatic: false,
IsLocal: false, IsLocal: false,
} }
if *api.app.Config().ServiceSettings.WebserverMode == "gzip" { if *api.srv.Config().ServiceSettings.WebserverMode == "gzip" {
return gziphandler.GzipHandler(handler) return gziphandler.GzipHandler(handler)
} }
return handler return handler
@@ -118,7 +118,7 @@ func (api *API) APISessionRequiredMfa(h func(*Context, http.ResponseWriter, *htt
// websocket. // websocket.
func (api *API) APIHandlerTrustRequester(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { func (api *API) APIHandlerTrustRequester(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
handler := &web.Handler{ handler := &web.Handler{
App: api.app, Srv: api.srv,
HandleFunc: h, HandleFunc: h,
HandlerName: web.GetHandlerName(h), HandlerName: web.GetHandlerName(h),
RequireSession: false, RequireSession: false,
@@ -127,7 +127,7 @@ func (api *API) APIHandlerTrustRequester(h func(*Context, http.ResponseWriter, *
IsStatic: false, IsStatic: false,
IsLocal: false, IsLocal: false,
} }
if *api.app.Config().ServiceSettings.WebserverMode == "gzip" { if *api.srv.Config().ServiceSettings.WebserverMode == "gzip" {
return gziphandler.GzipHandler(handler) return gziphandler.GzipHandler(handler)
} }
return handler return handler
@@ -138,7 +138,7 @@ func (api *API) APIHandlerTrustRequester(h func(*Context, http.ResponseWriter, *
// are allowed to be requested directly rather than via javascript/XMLHttpRequest, such as emoji or file uploads. // are allowed to be requested directly rather than via javascript/XMLHttpRequest, such as emoji or file uploads.
func (api *API) APISessionRequiredTrustRequester(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { func (api *API) APISessionRequiredTrustRequester(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
handler := &web.Handler{ handler := &web.Handler{
App: api.app, Srv: api.srv,
HandleFunc: h, HandleFunc: h,
HandlerName: web.GetHandlerName(h), HandlerName: web.GetHandlerName(h),
RequireSession: true, RequireSession: true,
@@ -147,7 +147,7 @@ func (api *API) APISessionRequiredTrustRequester(h func(*Context, http.ResponseW
IsStatic: false, IsStatic: false,
IsLocal: false, IsLocal: false,
} }
if *api.app.Config().ServiceSettings.WebserverMode == "gzip" { if *api.srv.Config().ServiceSettings.WebserverMode == "gzip" {
return gziphandler.GzipHandler(handler) return gziphandler.GzipHandler(handler)
} }
return handler return handler
@@ -158,7 +158,7 @@ func (api *API) APISessionRequiredTrustRequester(h func(*Context, http.ResponseW
// responding with HTTP 503 (Service Unavailable). // responding with HTTP 503 (Service Unavailable).
func (api *API) APISessionRequiredDisableWhenBusy(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { func (api *API) APISessionRequiredDisableWhenBusy(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
handler := &web.Handler{ handler := &web.Handler{
App: api.app, Srv: api.srv,
HandleFunc: h, HandleFunc: h,
HandlerName: web.GetHandlerName(h), HandlerName: web.GetHandlerName(h),
RequireSession: true, RequireSession: true,
@@ -168,7 +168,7 @@ func (api *API) APISessionRequiredDisableWhenBusy(h func(*Context, http.Response
IsLocal: false, IsLocal: false,
DisableWhenBusy: true, DisableWhenBusy: true,
} }
if *api.app.Config().ServiceSettings.WebserverMode == "gzip" { if *api.srv.Config().ServiceSettings.WebserverMode == "gzip" {
return gziphandler.GzipHandler(handler) return gziphandler.GzipHandler(handler)
} }
return handler return handler
@@ -181,7 +181,7 @@ func (api *API) APISessionRequiredDisableWhenBusy(h func(*Context, http.Response
// restrictions // restrictions
func (api *API) APILocal(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { func (api *API) APILocal(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
handler := &web.Handler{ handler := &web.Handler{
App: api.app, Srv: api.srv,
HandleFunc: h, HandleFunc: h,
HandlerName: web.GetHandlerName(h), HandlerName: web.GetHandlerName(h),
RequireSession: false, RequireSession: false,
@@ -191,7 +191,7 @@ func (api *API) APILocal(h func(*Context, http.ResponseWriter, *http.Request)) h
IsLocal: true, IsLocal: true,
} }
if *api.app.Config().ServiceSettings.WebserverMode == "gzip" { if *api.srv.Config().ServiceSettings.WebserverMode == "gzip" {
return gziphandler.GzipHandler(handler) return gziphandler.GzipHandler(handler)
} }
return handler return handler

Просмотреть файл

@@ -68,7 +68,7 @@ func TestAPIHandlersWithGzip(t *testing.T) {
th := Setup(t) th := Setup(t)
defer th.TearDown() defer th.TearDown()
api := Init(th.App, th.Server.Router) api := Init(th.Server)
session, _ := th.App.GetSession(th.Client.AuthToken) session, _ := th.App.GetSession(th.Client.AuthToken)
t.Run("with WebserverMode == \"gzip\"", func(t *testing.T) { t.Run("with WebserverMode == \"gzip\"", func(t *testing.T) {

Просмотреть файл

@@ -5,30 +5,13 @@ package api4
import ( import (
"net/http" "net/http"
"time"
"github.com/mattermost/mattermost-server/v6/model" "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/services/cache" "github.com/mattermost/mattermost-server/v6/shared/mlog"
) )
const OpenGraphMetadataCacheSize = 10000
var openGraphDataCache = cache.NewLRU(cache.LRUOptions{
Size: OpenGraphMetadataCacheSize,
})
func (api *API) InitOpenGraph() { func (api *API) InitOpenGraph() {
api.BaseRoutes.OpenGraph.Handle("", api.APISessionRequired(getOpenGraphMetadata)).Methods("POST") api.BaseRoutes.OpenGraph.Handle("", api.APISessionRequired(getOpenGraphMetadata)).Methods("POST")
// Dump the image cache if the proxy settings have changed. (need switch URLs to the correct proxy)
api.app.AddConfigListener(func(before, after *model.Config) {
if (before.ImageProxySettings.Enable != after.ImageProxySettings.Enable) ||
(before.ImageProxySettings.ImageProxyType != after.ImageProxySettings.ImageProxyType) ||
(before.ImageProxySettings.RemoteImageProxyURL != after.ImageProxySettings.RemoteImageProxyURL) ||
(before.ImageProxySettings.RemoteImageProxyOptions != after.ImageProxySettings.RemoteImageProxyOptions) {
openGraphDataCache.Purge()
}
})
} }
func getOpenGraphMetadata(c *Context, w http.ResponseWriter, r *http.Request) { func getOpenGraphMetadata(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -46,20 +29,13 @@ func getOpenGraphMetadata(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
var ogJSONGeneric []byte buf, err := c.App.GetOpenGraphMetadata(url)
err := openGraphDataCache.Get(url, &ogJSONGeneric)
if err == nil {
w.Write(ogJSONGeneric)
return
}
og := c.App.GetOpenGraphMetadata(url)
ogJSON, err := og.ToJSON()
openGraphDataCache.SetWithExpiry(url, ogJSON, 1*time.Hour)
if err != nil { if err != nil {
mlog.Warn("GetOpenGraphMetadata request failed",
mlog.String("requestURL", url),
mlog.Err(err))
w.Write([]byte(`{"url": ""}`)) w.Write([]byte(`{"url": ""}`))
return return
} }
w.Write(buf)
w.Write(ogJSON)
} }

Просмотреть файл

@@ -601,7 +601,7 @@ func TestCreatePostCheckOnlineStatus(t *testing.T) {
th := Setup(t).InitBasic() th := Setup(t).InitBasic()
defer th.TearDown() defer th.TearDown()
api := Init(th.App, th.Server.Router) api := Init(th.Server)
session, _ := th.App.GetSession(th.Client.AuthToken) session, _ := th.App.GetSession(th.Client.AuthToken)
cli := th.CreateClient() cli := th.CreateClient()

Просмотреть файл

@@ -748,7 +748,7 @@ func TestServerBusy503(t *testing.T) {
func TestPushNotificationAck(t *testing.T) { func TestPushNotificationAck(t *testing.T) {
th := Setup(t).InitBasic() th := Setup(t).InitBasic()
api := Init(th.App, th.Server.Router) api := Init(th.Server)
session, _ := th.App.GetSession(th.Client.AuthToken) session, _ := th.App.GetSession(th.Client.AuthToken)
defer th.TearDown() defer th.TearDown()

Просмотреть файл

@@ -18,7 +18,6 @@ import (
"reflect" "reflect"
"time" "time"
"github.com/dyatlov/go-opengraph/opengraph"
"github.com/mattermost/mattermost-server/v6/app/request" "github.com/mattermost/mattermost-server/v6/app/request"
"github.com/mattermost/mattermost-server/v6/audit" "github.com/mattermost/mattermost-server/v6/audit"
"github.com/mattermost/mattermost-server/v6/einterfaces" "github.com/mattermost/mattermost-server/v6/einterfaces"
@@ -654,7 +653,7 @@ type AppIface interface {
GetOAuthLoginEndpoint(w http.ResponseWriter, r *http.Request, service, teamID, action, redirectTo, loginHint string, isMobile bool) (string, *model.AppError) GetOAuthLoginEndpoint(w http.ResponseWriter, r *http.Request, service, teamID, action, redirectTo, loginHint string, isMobile bool) (string, *model.AppError)
GetOAuthSignupEndpoint(w http.ResponseWriter, r *http.Request, service, teamID string) (string, *model.AppError) GetOAuthSignupEndpoint(w http.ResponseWriter, r *http.Request, service, teamID string) (string, *model.AppError)
GetOAuthStateToken(token string) (*model.Token, *model.AppError) GetOAuthStateToken(token string) (*model.Token, *model.AppError)
GetOpenGraphMetadata(requestURL string) *opengraph.OpenGraph GetOpenGraphMetadata(requestURL string) ([]byte, error)
GetOrCreateDirectChannel(c *request.Context, userID, otherUserID string, channelOptions ...model.ChannelOption) (*model.Channel, *model.AppError) GetOrCreateDirectChannel(c *request.Context, userID, otherUserID string, channelOptions ...model.ChannelOption) (*model.Channel, *model.AppError)
GetOutgoingWebhook(hookID string) (*model.OutgoingWebhook, *model.AppError) GetOutgoingWebhook(hookID string) (*model.OutgoingWebhook, *model.AppError)
GetOutgoingWebhooksForChannelPageByUser(channelID string, userID string, page, perPage int) ([]*model.OutgoingWebhook, *model.AppError) GetOutgoingWebhooksForChannelPageByUser(channelID string, userID string, page, perPage int) ([]*model.OutgoingWebhook, *model.AppError)

Просмотреть файл

@@ -7,6 +7,7 @@ import (
"html" "html"
"io" "io"
"net/url" "net/url"
"time"
"github.com/dyatlov/go-opengraph/opengraph" "github.com/dyatlov/go-opengraph/opengraph"
"golang.org/x/net/html/charset" "golang.org/x/net/html/charset"
@@ -14,16 +15,36 @@ import (
"github.com/mattermost/mattermost-server/v6/shared/mlog" "github.com/mattermost/mattermost-server/v6/shared/mlog"
) )
const MaxOpenGraphResponseSize = 1024 * 1024 * 50 const (
MaxOpenGraphResponseSize = 1024 * 1024 * 50
openGraphMetadataCacheSize = 10000
)
func (a *App) GetOpenGraphMetadata(requestURL string) ([]byte, error) {
var ogJSONGeneric []byte
err := a.Srv().openGraphDataCache.Get(requestURL, &ogJSONGeneric)
if err == nil {
return ogJSONGeneric, nil
}
func (a *App) GetOpenGraphMetadata(requestURL string) *opengraph.OpenGraph {
res, err := a.HTTPService().MakeClient(false).Get(requestURL) res, err := a.HTTPService().MakeClient(false).Get(requestURL)
if err != nil { if err != nil {
mlog.Debug("GetOpenGraphMetadata request failed", mlog.String("requestURL", requestURL), mlog.Err(err)) return nil, err
return nil
} }
defer res.Body.Close() defer res.Body.Close()
return a.parseOpenGraphMetadata(requestURL, res.Body, res.Header.Get("Content-Type"))
graph := a.parseOpenGraphMetadata(requestURL, res.Body, res.Header.Get("Content-Type"))
ogJSON, err := graph.ToJSON()
if err != nil {
return nil, err
}
err = a.Srv().openGraphDataCache.SetWithExpiry(requestURL, ogJSON, 1*time.Hour)
if err != nil {
return nil, err
}
return ogJSON, nil
} }
func (a *App) parseOpenGraphMetadata(requestURL string, body io.Reader, contentType string) *opengraph.OpenGraph { func (a *App) parseOpenGraphMetadata(requestURL string, body io.Reader, contentType string) *opengraph.OpenGraph {

Просмотреть файл

@@ -18,7 +18,6 @@ import (
"reflect" "reflect"
"time" "time"
"github.com/dyatlov/go-opengraph/opengraph"
"github.com/mattermost/mattermost-server/v6/app" "github.com/mattermost/mattermost-server/v6/app"
"github.com/mattermost/mattermost-server/v6/app/request" "github.com/mattermost/mattermost-server/v6/app/request"
"github.com/mattermost/mattermost-server/v6/audit" "github.com/mattermost/mattermost-server/v6/audit"
@@ -6899,7 +6898,7 @@ func (a *OpenTracingAppLayer) GetOAuthStateToken(token string) (*model.Token, *m
return resultVar0, resultVar1 return resultVar0, resultVar1
} }
func (a *OpenTracingAppLayer) GetOpenGraphMetadata(requestURL string) *opengraph.OpenGraph { func (a *OpenTracingAppLayer) GetOpenGraphMetadata(requestURL string) ([]byte, error) {
origCtx := a.ctx origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetOpenGraphMetadata") span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetOpenGraphMetadata")
@@ -6911,9 +6910,14 @@ func (a *OpenTracingAppLayer) GetOpenGraphMetadata(requestURL string) *opengraph
}() }()
defer span.Finish() defer span.Finish()
resultVar0 := a.app.GetOpenGraphMetadata(requestURL) resultVar0, resultVar1 := a.app.GetOpenGraphMetadata(requestURL)
return resultVar0 if resultVar1 != nil {
span.LogFields(spanlog.Error(resultVar1))
ext.Error.Set(span, true)
}
return resultVar0, resultVar1
} }
func (a *OpenTracingAppLayer) GetOrCreateDirectChannel(c *request.Context, userID string, otherUserID string, channelOptions ...model.ChannelOption) (*model.Channel, *model.AppError) { func (a *OpenTracingAppLayer) GetOrCreateDirectChannel(c *request.Context, userID string, otherUserID string, channelOptions ...model.ChannelOption) (*model.Channel, *model.AppError) {

Просмотреть файл

@@ -137,6 +137,7 @@ type Server struct {
htmlTemplateWatcher *templates.Container htmlTemplateWatcher *templates.Container
seenPendingPostIdsCache cache.Cache seenPendingPostIdsCache cache.Cache
statusCache cache.Cache statusCache cache.Cache
openGraphDataCache cache.Cache
configListenerId string configListenerId string
licenseListenerId string licenseListenerId string
clusterLeaderListenerId string clusterLeaderListenerId string
@@ -349,6 +350,11 @@ func NewServer(options ...Option) (*Server, error) {
}); err != nil { }); err != nil {
return nil, errors.Wrap(err, "Unable to create status cache") return nil, errors.Wrap(err, "Unable to create status cache")
} }
if s.openGraphDataCache, err = s.CacheProvider.NewCache(&cache.CacheOptions{
Size: openGraphMetadataCacheSize,
}); err != nil {
return nil, errors.Wrap(err, "Unable to create opengraphdata cache")
}
s.createPushNotificationsHub() s.createPushNotificationsHub()
@@ -708,6 +714,16 @@ func NewServer(options ...Option) (*Server, error) {
} }
}) })
// Dump the image cache if the proxy settings have changed. (need switch URLs to the correct proxy)
s.AddConfigListener(func(oldCfg, newCfg *model.Config) {
if (oldCfg.ImageProxySettings.Enable != newCfg.ImageProxySettings.Enable) ||
(oldCfg.ImageProxySettings.ImageProxyType != newCfg.ImageProxySettings.ImageProxyType) ||
(oldCfg.ImageProxySettings.RemoteImageProxyURL != newCfg.ImageProxySettings.RemoteImageProxyURL) ||
(oldCfg.ImageProxySettings.RemoteImageProxyOptions != newCfg.ImageProxySettings.RemoteImageProxyOptions) {
s.openGraphDataCache.Purge()
}
})
return s, nil return s, nil
} }

Просмотреть файл

@@ -93,17 +93,14 @@ func runServer(configStore *config.Store, interruptChan chan os.Signal) error {
} }
}() }()
a := app.New(app.ServerConnector(server.Channels())) api := api4.Init(server)
api := api4.Init(a, server.Router)
wsapi.Init(server) wsapi.Init(server)
web.New(a, server.Router) web.New(server)
api4.InitLocal(a, server.LocalRouter)
serverErr := server.Start() err = server.Start()
if serverErr != nil { if err != nil {
mlog.Critical(serverErr.Error()) mlog.Critical(err.Error())
return serverErr return err
} }
// If we allow testing then listen for manual testing URL hits // If we allow testing then listen for manual testing URL hits

Просмотреть файл

@@ -58,7 +58,7 @@ func webClientTestsCmdF(command *cobra.Command, args []string) error {
return serverErr return serverErr
} }
api4.Init(a, a.Srv().Router) api4.Init(a.Srv())
wsapi.Init(a.Srv()) wsapi.Init(a.Srv())
a.UpdateConfig(setupClientTests) a.UpdateConfig(setupClientTests)
runWebClientTests() runWebClientTests()
@@ -79,7 +79,7 @@ func serverForWebClientTestsCmdF(command *cobra.Command, args []string) error {
return serverErr return serverErr
} }
api4.Init(a, a.Srv().Router) api4.Init(a.Srv())
wsapi.Init(a.Srv()) wsapi.Init(a.Srv())
a.UpdateConfig(setupClientTests) a.UpdateConfig(setupClientTests)

Просмотреть файл

@@ -41,7 +41,7 @@ func GetHandlerName(h func(*Context, http.ResponseWriter, *http.Request)) string
func (w *Web) NewHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { func (w *Web) NewHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
return &Handler{ return &Handler{
App: w.app, Srv: w.srv,
HandleFunc: h, HandleFunc: h,
HandlerName: GetHandlerName(h), HandlerName: GetHandlerName(h),
RequireSession: false, RequireSession: false,
@@ -55,10 +55,10 @@ func (w *Web) NewHandler(h func(*Context, http.ResponseWriter, *http.Request)) h
func (w *Web) NewStaticHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { func (w *Web) NewStaticHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
// Determine the CSP SHA directive needed for subpath support, if any. This value is fixed // Determine the CSP SHA directive needed for subpath support, if any. This value is fixed
// on server start and intentionally requires a restart to take effect. // on server start and intentionally requires a restart to take effect.
subpath, _ := utils.GetSubpathFromConfig(w.app.Config()) subpath, _ := utils.GetSubpathFromConfig(w.srv.Config())
return &Handler{ return &Handler{
App: w.app, Srv: w.srv,
HandleFunc: h, HandleFunc: h,
HandlerName: GetHandlerName(h), HandlerName: GetHandlerName(h),
RequireSession: false, RequireSession: false,
@@ -71,7 +71,7 @@ func (w *Web) NewStaticHandler(h func(*Context, http.ResponseWriter, *http.Reque
} }
type Handler struct { type Handler struct {
App app.AppIface Srv *app.Server
HandleFunc func(*Context, http.ResponseWriter, *http.Request) HandleFunc func(*Context, http.ResponseWriter, *http.Request)
HandlerName string HandlerName string
RequireSession bool RequireSession bool
@@ -90,6 +90,8 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w = newWrappedWriter(w) w = newWrappedWriter(w)
now := time.Now() now := time.Now()
appInstance := app.New(app.ServerConnector(h.Srv.Channels()))
requestID := model.NewId() requestID := model.NewId()
var statusCode string var statusCode string
defer func() { defer func() {
@@ -107,7 +109,7 @@ func (h Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
c := &Context{ c := &Context{
AppContext: &request.Context{}, AppContext: &request.Context{},
App: h.App, App: appInstance,
} }
t, _ := i18n.GetTranslationsAndLocaleFromRequest(r) t, _ := i18n.GetTranslationsAndLocaleFromRequest(r)
@@ -394,7 +396,7 @@ func (h *Handler) checkCSRFToken(c *Context, r *http.Request, token string, toke
// granted. // granted.
func (w *Web) APIHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { func (w *Web) APIHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
handler := &Handler{ handler := &Handler{
App: w.app, Srv: w.srv,
HandleFunc: h, HandleFunc: h,
HandlerName: GetHandlerName(h), HandlerName: GetHandlerName(h),
RequireSession: false, RequireSession: false,
@@ -403,7 +405,7 @@ func (w *Web) APIHandler(h func(*Context, http.ResponseWriter, *http.Request)) h
IsStatic: false, IsStatic: false,
IsLocal: false, IsLocal: false,
} }
if *w.app.Config().ServiceSettings.WebserverMode == "gzip" { if *w.srv.Config().ServiceSettings.WebserverMode == "gzip" {
return gziphandler.GzipHandler(handler) return gziphandler.GzipHandler(handler)
} }
return handler return handler
@@ -414,7 +416,7 @@ func (w *Web) APIHandler(h func(*Context, http.ResponseWriter, *http.Request)) h
// websocket. // websocket.
func (w *Web) APIHandlerTrustRequester(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { func (w *Web) APIHandlerTrustRequester(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
handler := &Handler{ handler := &Handler{
App: w.app, Srv: w.srv,
HandleFunc: h, HandleFunc: h,
HandlerName: GetHandlerName(h), HandlerName: GetHandlerName(h),
RequireSession: false, RequireSession: false,
@@ -423,7 +425,7 @@ func (w *Web) APIHandlerTrustRequester(h func(*Context, http.ResponseWriter, *ht
IsStatic: false, IsStatic: false,
IsLocal: false, IsLocal: false,
} }
if *w.app.Config().ServiceSettings.WebserverMode == "gzip" { if *w.srv.Config().ServiceSettings.WebserverMode == "gzip" {
return gziphandler.GzipHandler(handler) return gziphandler.GzipHandler(handler)
} }
return handler return handler
@@ -433,7 +435,7 @@ func (w *Web) APIHandlerTrustRequester(h func(*Context, http.ResponseWriter, *ht
// be granted. // be granted.
func (w *Web) APISessionRequired(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler { func (w *Web) APISessionRequired(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
handler := &Handler{ handler := &Handler{
App: w.app, Srv: w.srv,
HandleFunc: h, HandleFunc: h,
HandlerName: GetHandlerName(h), HandlerName: GetHandlerName(h),
RequireSession: true, RequireSession: true,
@@ -442,7 +444,7 @@ func (w *Web) APISessionRequired(h func(*Context, http.ResponseWriter, *http.Req
IsStatic: false, IsStatic: false,
IsLocal: false, IsLocal: false,
} }
if *w.app.Config().ServiceSettings.WebserverMode == "gzip" { if *w.srv.Config().ServiceSettings.WebserverMode == "gzip" {
return gziphandler.GzipHandler(handler) return gziphandler.GzipHandler(handler)
} }
return handler return handler

Просмотреть файл

@@ -25,7 +25,7 @@ func TestHandlerServeHTTPErrors(t *testing.T) {
th := SetupWithStoreMock(t) th := SetupWithStoreMock(t)
defer th.TearDown() defer th.TearDown()
web := New(th.App, th.Server.Router) web := New(th.Server)
handler := web.NewHandler(handlerForHTTPErrors) handler := web.NewHandler(handlerForHTTPErrors)
var flagtests = []struct { var flagtests = []struct {
@@ -84,7 +84,7 @@ func TestHandlerServeHTTPSecureTransport(t *testing.T) {
*config.ServiceSettings.TLSStrictTransportMaxAge = 6000 *config.ServiceSettings.TLSStrictTransportMaxAge = 6000
}) })
web := New(th.App, th.Server.Router) web := New(th.Server)
handler := web.NewHandler(handlerForHTTPSecureTransport) handler := web.NewHandler(handlerForHTTPSecureTransport)
request := httptest.NewRequest("GET", "/api/v4/test", nil) request := httptest.NewRequest("GET", "/api/v4/test", nil)
@@ -136,10 +136,10 @@ func TestHandlerServeCSRFToken(t *testing.T) {
t.Errorf("Expected nil, got %s", err) t.Errorf("Expected nil, got %s", err)
} }
web := New(th.App, th.Server.Router) web := New(th.Server)
handler := Handler{ handler := Handler{
App: web.app, Srv: web.srv,
HandleFunc: handlerForCSRFToken, HandleFunc: handlerForCSRFToken,
RequireSession: true, RequireSession: true,
TrustRequester: false, TrustRequester: false,
@@ -219,7 +219,7 @@ func TestHandlerServeCSRFToken(t *testing.T) {
// Handler with RequireSession set to false // Handler with RequireSession set to false
handlerNoSession := Handler{ handlerNoSession := Handler{
App: th.App, Srv: th.Server,
HandleFunc: handlerForCSRFToken, HandleFunc: handlerForCSRFToken,
RequireSession: false, RequireSession: false,
TrustRequester: false, TrustRequester: false,
@@ -263,10 +263,10 @@ func TestHandlerServeCSPHeader(t *testing.T) {
th := SetupWithStoreMock(t) th := SetupWithStoreMock(t)
defer th.TearDown() defer th.TearDown()
web := New(th.App, th.Server.Router) web := New(th.Server)
handler := Handler{ handler := Handler{
App: web.app, Srv: web.srv,
HandleFunc: handlerForCSPHeader, HandleFunc: handlerForCSPHeader,
RequireSession: false, RequireSession: false,
TrustRequester: false, TrustRequester: false,
@@ -285,10 +285,10 @@ func TestHandlerServeCSPHeader(t *testing.T) {
th := SetupWithStoreMock(t) th := SetupWithStoreMock(t)
defer th.TearDown() defer th.TearDown()
web := New(th.App, th.Server.Router) web := New(th.Server)
handler := Handler{ handler := Handler{
App: web.app, Srv: web.srv,
HandleFunc: handlerForCSPHeader, HandleFunc: handlerForCSPHeader,
RequireSession: false, RequireSession: false,
TrustRequester: false, TrustRequester: false,
@@ -325,10 +325,10 @@ func TestHandlerServeCSPHeader(t *testing.T) {
*cfg.ServiceSettings.SiteURL = *cfg.ServiceSettings.SiteURL + "/subpath" *cfg.ServiceSettings.SiteURL = *cfg.ServiceSettings.SiteURL + "/subpath"
}) })
web := New(th.App, th.Server.Router) web := New(th.Server)
handler := Handler{ handler := Handler{
App: web.app, Srv: web.srv,
HandleFunc: handlerForCSPHeader, HandleFunc: handlerForCSPHeader,
RequireSession: false, RequireSession: false,
TrustRequester: false, TrustRequester: false,
@@ -380,10 +380,10 @@ func TestHandlerServeInvalidToken(t *testing.T) {
*cfg.ServiceSettings.SiteURL = tc.SiteURL *cfg.ServiceSettings.SiteURL = tc.SiteURL
}) })
web := New(th.App, th.Server.Router) web := New(th.Server)
handler := Handler{ handler := Handler{
App: web.app, Srv: web.srv,
HandleFunc: handlerForCSRFToken, HandleFunc: handlerForCSRFToken,
RequireSession: true, RequireSession: true,
TrustRequester: false, TrustRequester: false,

Просмотреть файл

@@ -21,20 +21,20 @@ import (
var robotsTxt = []byte("User-agent: *\nDisallow: /\n") var robotsTxt = []byte("User-agent: *\nDisallow: /\n")
func (w *Web) InitStatic() { func (w *Web) InitStatic() {
if *w.app.Config().ServiceSettings.WebserverMode != "disabled" { if *w.srv.Config().ServiceSettings.WebserverMode != "disabled" {
if err := utils.UpdateAssetsSubpathFromConfig(w.app.Config()); err != nil { if err := utils.UpdateAssetsSubpathFromConfig(w.srv.Config()); err != nil {
mlog.Error("Failed to update assets subpath from config", mlog.Err(err)) mlog.Error("Failed to update assets subpath from config", mlog.Err(err))
} }
staticDir, _ := fileutils.FindDir(model.ClientDir) staticDir, _ := fileutils.FindDir(model.ClientDir)
mlog.Debug("Using client directory", mlog.String("clientDir", staticDir)) mlog.Debug("Using client directory", mlog.String("clientDir", staticDir))
subpath, _ := utils.GetSubpathFromConfig(w.app.Config()) subpath, _ := utils.GetSubpathFromConfig(w.srv.Config())
staticHandler := staticFilesHandler(http.StripPrefix(path.Join(subpath, "static"), http.FileServer(http.Dir(staticDir)))) staticHandler := staticFilesHandler(http.StripPrefix(path.Join(subpath, "static"), http.FileServer(http.Dir(staticDir))))
pluginHandler := staticFilesHandler(http.StripPrefix(path.Join(subpath, "static", "plugins"), http.FileServer(http.Dir(*w.app.Config().PluginSettings.ClientDirectory)))) pluginHandler := staticFilesHandler(http.StripPrefix(path.Join(subpath, "static", "plugins"), http.FileServer(http.Dir(*w.srv.Config().PluginSettings.ClientDirectory))))
if *w.app.Config().ServiceSettings.WebserverMode == "gzip" { if *w.srv.Config().ServiceSettings.WebserverMode == "gzip" {
staticHandler = gziphandler.GzipHandler(staticHandler) staticHandler = gziphandler.GzipHandler(staticHandler)
pluginHandler = gziphandler.GzipHandler(pluginHandler) pluginHandler = gziphandler.GzipHandler(pluginHandler)
} }

Просмотреть файл

@@ -18,16 +18,16 @@ import (
) )
type Web struct { type Web struct {
app app.AppIface srv *app.Server
MainRouter *mux.Router MainRouter *mux.Router
} }
func New(a app.AppIface, root *mux.Router) *Web { func New(srv *app.Server) *Web {
mlog.Debug("Initializing web routes") mlog.Debug("Initializing web routes")
web := &Web{ web := &Web{
app: a, srv: srv,
MainRouter: root, MainRouter: srv.Router,
} }
web.InitOAuth() web.InitOAuth()

Просмотреть файл

@@ -122,7 +122,7 @@ func setupTestHelper(tb testing.TB, includeCacheLayer bool) *TestHelper {
ctx := &request.Context{} ctx := &request.Context{}
a := app.New(app.ServerConnector(s.Channels())) a := app.New(app.ServerConnector(s.Channels()))
web := New(a, s.Router) web := New(s)
URL = fmt.Sprintf("http://localhost:%v", s.ListenAddr.Port) URL = fmt.Sprintf("http://localhost:%v", s.ListenAddr.Port)
apiClient = model.NewAPIv4Client(URL) apiClient = model.NewAPIv4Client(URL)