Improve API4 initialization (#18680)
* 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 ```
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
43a99a5783
Коммит
c27814393d
27
api4/api.go
27
api4/api.go
@@ -135,18 +135,18 @@ type Routes struct {
|
||||
}
|
||||
|
||||
type API struct {
|
||||
app app.AppIface
|
||||
srv *app.Server
|
||||
BaseRoutes *Routes
|
||||
}
|
||||
|
||||
func Init(a app.AppIface, root *mux.Router) *API {
|
||||
func Init(srv *app.Server) *API {
|
||||
api := &API{
|
||||
app: a,
|
||||
srv: srv,
|
||||
BaseRoutes: &Routes{},
|
||||
}
|
||||
|
||||
api.BaseRoutes.Root = root
|
||||
api.BaseRoutes.APIRoot = root.PathPrefix(model.APIURLSuffix).Subrouter()
|
||||
api.BaseRoutes.Root = srv.Router
|
||||
api.BaseRoutes.APIRoot = srv.Router.PathPrefix(model.APIURLSuffix).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()
|
||||
@@ -293,19 +293,21 @@ func Init(a app.AppIface, root *mux.Router) *API {
|
||||
api.InitPermissions()
|
||||
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
|
||||
}
|
||||
|
||||
func InitLocal(a app.AppIface, root *mux.Router) *API {
|
||||
func InitLocal(srv *app.Server) *API {
|
||||
api := &API{
|
||||
app: a,
|
||||
srv: srv,
|
||||
BaseRoutes: &Routes{},
|
||||
}
|
||||
|
||||
api.BaseRoutes.Root = root
|
||||
api.BaseRoutes.APIRoot = root.PathPrefix(model.APIURLSuffix).Subrouter()
|
||||
api.BaseRoutes.Root = srv.LocalRouter
|
||||
api.BaseRoutes.APIRoot = srv.LocalRouter.PathPrefix(model.APIURLSuffix).Subrouter()
|
||||
|
||||
api.BaseRoutes.Users = api.BaseRoutes.APIRoot.PathPrefix("/users").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.InitSamlLocal()
|
||||
|
||||
root.Handle("/api/v4/{anything:.*}", http.HandlerFunc(api.Handle404))
|
||||
srv.LocalRouter.Handle("/api/v4/{anything:.*}", http.HandlerFunc(api.Handle404))
|
||||
|
||||
return api
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
@@ -177,9 +177,8 @@ func setupTestHelper(dbStore store.Store, searchEngine *searchengine.Broker, ent
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Init(th.App, th.App.Srv().Router)
|
||||
InitLocal(th.App, th.App.Srv().LocalRouter)
|
||||
web.New(th.App, th.App.Srv().Router)
|
||||
Init(th.App.Srv())
|
||||
web.New(th.App.Srv())
|
||||
wsapi.Init(th.App.Srv())
|
||||
|
||||
if enterprise {
|
||||
|
||||
@@ -17,7 +17,7 @@ type Context = web.Context
|
||||
// granted.
|
||||
func (api *API) APIHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
|
||||
handler := &web.Handler{
|
||||
App: api.app,
|
||||
Srv: api.srv,
|
||||
HandleFunc: h,
|
||||
HandlerName: web.GetHandlerName(h),
|
||||
RequireSession: false,
|
||||
@@ -26,7 +26,7 @@ func (api *API) APIHandler(h func(*Context, http.ResponseWriter, *http.Request))
|
||||
IsStatic: false,
|
||||
IsLocal: false,
|
||||
}
|
||||
if *api.app.Config().ServiceSettings.WebserverMode == "gzip" {
|
||||
if *api.srv.Config().ServiceSettings.WebserverMode == "gzip" {
|
||||
return gziphandler.GzipHandler(handler)
|
||||
}
|
||||
return handler
|
||||
@@ -36,7 +36,7 @@ func (api *API) APIHandler(h func(*Context, http.ResponseWriter, *http.Request))
|
||||
// be granted.
|
||||
func (api *API) APISessionRequired(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
|
||||
handler := &web.Handler{
|
||||
App: api.app,
|
||||
Srv: api.srv,
|
||||
HandleFunc: h,
|
||||
HandlerName: web.GetHandlerName(h),
|
||||
RequireSession: true,
|
||||
@@ -45,7 +45,7 @@ func (api *API) APISessionRequired(h func(*Context, http.ResponseWriter, *http.R
|
||||
IsStatic: false,
|
||||
IsLocal: false,
|
||||
}
|
||||
if *api.app.Config().ServiceSettings.WebserverMode == "gzip" {
|
||||
if *api.srv.Config().ServiceSettings.WebserverMode == "gzip" {
|
||||
return gziphandler.GzipHandler(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
|
||||
func (api *API) CloudAPIKeyRequired(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
|
||||
handler := &web.Handler{
|
||||
App: api.app,
|
||||
Srv: api.srv,
|
||||
HandleFunc: h,
|
||||
HandlerName: web.GetHandlerName(h),
|
||||
RequireSession: false,
|
||||
@@ -65,7 +65,7 @@ func (api *API) CloudAPIKeyRequired(h func(*Context, http.ResponseWriter, *http.
|
||||
IsStatic: false,
|
||||
IsLocal: false,
|
||||
}
|
||||
if *api.app.Config().ServiceSettings.WebserverMode == "gzip" {
|
||||
if *api.srv.Config().ServiceSettings.WebserverMode == "gzip" {
|
||||
return gziphandler.GzipHandler(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.
|
||||
func (api *API) RemoteClusterTokenRequired(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
|
||||
handler := &web.Handler{
|
||||
App: api.app,
|
||||
Srv: api.srv,
|
||||
HandleFunc: h,
|
||||
HandlerName: web.GetHandlerName(h),
|
||||
RequireSession: false,
|
||||
@@ -86,7 +86,7 @@ func (api *API) RemoteClusterTokenRequired(h func(*Context, http.ResponseWriter,
|
||||
IsStatic: false,
|
||||
IsLocal: false,
|
||||
}
|
||||
if *api.app.Config().ServiceSettings.WebserverMode == "gzip" {
|
||||
if *api.srv.Config().ServiceSettings.WebserverMode == "gzip" {
|
||||
return gziphandler.GzipHandler(handler)
|
||||
}
|
||||
return handler
|
||||
@@ -97,7 +97,7 @@ func (api *API) RemoteClusterTokenRequired(h func(*Context, http.ResponseWriter,
|
||||
// authentication must be waived.
|
||||
func (api *API) APISessionRequiredMfa(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
|
||||
handler := &web.Handler{
|
||||
App: api.app,
|
||||
Srv: api.srv,
|
||||
HandleFunc: h,
|
||||
HandlerName: web.GetHandlerName(h),
|
||||
RequireSession: true,
|
||||
@@ -106,7 +106,7 @@ func (api *API) APISessionRequiredMfa(h func(*Context, http.ResponseWriter, *htt
|
||||
IsStatic: false,
|
||||
IsLocal: false,
|
||||
}
|
||||
if *api.app.Config().ServiceSettings.WebserverMode == "gzip" {
|
||||
if *api.srv.Config().ServiceSettings.WebserverMode == "gzip" {
|
||||
return gziphandler.GzipHandler(handler)
|
||||
}
|
||||
return handler
|
||||
@@ -118,7 +118,7 @@ func (api *API) APISessionRequiredMfa(h func(*Context, http.ResponseWriter, *htt
|
||||
// websocket.
|
||||
func (api *API) APIHandlerTrustRequester(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
|
||||
handler := &web.Handler{
|
||||
App: api.app,
|
||||
Srv: api.srv,
|
||||
HandleFunc: h,
|
||||
HandlerName: web.GetHandlerName(h),
|
||||
RequireSession: false,
|
||||
@@ -127,7 +127,7 @@ func (api *API) APIHandlerTrustRequester(h func(*Context, http.ResponseWriter, *
|
||||
IsStatic: false,
|
||||
IsLocal: false,
|
||||
}
|
||||
if *api.app.Config().ServiceSettings.WebserverMode == "gzip" {
|
||||
if *api.srv.Config().ServiceSettings.WebserverMode == "gzip" {
|
||||
return gziphandler.GzipHandler(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.
|
||||
func (api *API) APISessionRequiredTrustRequester(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
|
||||
handler := &web.Handler{
|
||||
App: api.app,
|
||||
Srv: api.srv,
|
||||
HandleFunc: h,
|
||||
HandlerName: web.GetHandlerName(h),
|
||||
RequireSession: true,
|
||||
@@ -147,7 +147,7 @@ func (api *API) APISessionRequiredTrustRequester(h func(*Context, http.ResponseW
|
||||
IsStatic: false,
|
||||
IsLocal: false,
|
||||
}
|
||||
if *api.app.Config().ServiceSettings.WebserverMode == "gzip" {
|
||||
if *api.srv.Config().ServiceSettings.WebserverMode == "gzip" {
|
||||
return gziphandler.GzipHandler(handler)
|
||||
}
|
||||
return handler
|
||||
@@ -158,7 +158,7 @@ func (api *API) APISessionRequiredTrustRequester(h func(*Context, http.ResponseW
|
||||
// responding with HTTP 503 (Service Unavailable).
|
||||
func (api *API) APISessionRequiredDisableWhenBusy(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
|
||||
handler := &web.Handler{
|
||||
App: api.app,
|
||||
Srv: api.srv,
|
||||
HandleFunc: h,
|
||||
HandlerName: web.GetHandlerName(h),
|
||||
RequireSession: true,
|
||||
@@ -168,7 +168,7 @@ func (api *API) APISessionRequiredDisableWhenBusy(h func(*Context, http.Response
|
||||
IsLocal: false,
|
||||
DisableWhenBusy: true,
|
||||
}
|
||||
if *api.app.Config().ServiceSettings.WebserverMode == "gzip" {
|
||||
if *api.srv.Config().ServiceSettings.WebserverMode == "gzip" {
|
||||
return gziphandler.GzipHandler(handler)
|
||||
}
|
||||
return handler
|
||||
@@ -181,7 +181,7 @@ func (api *API) APISessionRequiredDisableWhenBusy(h func(*Context, http.Response
|
||||
// restrictions
|
||||
func (api *API) APILocal(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
|
||||
handler := &web.Handler{
|
||||
App: api.app,
|
||||
Srv: api.srv,
|
||||
HandleFunc: h,
|
||||
HandlerName: web.GetHandlerName(h),
|
||||
RequireSession: false,
|
||||
@@ -191,7 +191,7 @@ func (api *API) APILocal(h func(*Context, http.ResponseWriter, *http.Request)) h
|
||||
IsLocal: true,
|
||||
}
|
||||
|
||||
if *api.app.Config().ServiceSettings.WebserverMode == "gzip" {
|
||||
if *api.srv.Config().ServiceSettings.WebserverMode == "gzip" {
|
||||
return gziphandler.GzipHandler(handler)
|
||||
}
|
||||
return handler
|
||||
|
||||
@@ -68,7 +68,7 @@ func TestAPIHandlersWithGzip(t *testing.T) {
|
||||
th := Setup(t)
|
||||
defer th.TearDown()
|
||||
|
||||
api := Init(th.App, th.Server.Router)
|
||||
api := Init(th.Server)
|
||||
session, _ := th.App.GetSession(th.Client.AuthToken)
|
||||
|
||||
t.Run("with WebserverMode == \"gzip\"", func(t *testing.T) {
|
||||
|
||||
@@ -5,30 +5,13 @@ package api4
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"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() {
|
||||
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) {
|
||||
@@ -46,20 +29,13 @@ func getOpenGraphMetadata(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
var ogJSONGeneric []byte
|
||||
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)
|
||||
buf, err := c.App.GetOpenGraphMetadata(url)
|
||||
if err != nil {
|
||||
mlog.Warn("GetOpenGraphMetadata request failed",
|
||||
mlog.String("requestURL", url),
|
||||
mlog.Err(err))
|
||||
w.Write([]byte(`{"url": ""}`))
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(ogJSON)
|
||||
w.Write(buf)
|
||||
}
|
||||
|
||||
@@ -601,7 +601,7 @@ func TestCreatePostCheckOnlineStatus(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
api := Init(th.App, th.Server.Router)
|
||||
api := Init(th.Server)
|
||||
session, _ := th.App.GetSession(th.Client.AuthToken)
|
||||
|
||||
cli := th.CreateClient()
|
||||
|
||||
@@ -748,7 +748,7 @@ func TestServerBusy503(t *testing.T) {
|
||||
|
||||
func TestPushNotificationAck(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
api := Init(th.App, th.Server.Router)
|
||||
api := Init(th.Server)
|
||||
session, _ := th.App.GetSession(th.Client.AuthToken)
|
||||
defer th.TearDown()
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user